According to this, Scala 3 offers a new way to define programs that can be invoked from the command line: A @main
annotation on a method turns this method into an executable program.
I followed exactly the code
@main def happyBirthday(age: Int, name: String, others: String*) =
val suffix =
age % 100 match
case 11 | 12 | 13 => "th"
case _ =>
age % 10 match
case 1 => "st"
case 2 => "nd"
case 3 => "rd"
case _ => "th"
val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name")
for other <- others do bldr.append(" and ").append(other)
bldr.toString
and compiled it with scalac. Subsequent run produces an error
scala happyBirthday 23 Lisa Peter
Illegal command line: java.lang.NumberFormatException: For input string: “happyBirthday”
It is clear to me that the program name (which should be the argument 0) is mistakenly taken as the first numeric argument. What is the problem and how to solve it?
Details
java -version
java version "1.8.0_321"
Java(TM) SE Runtime Environment (build 1.8.0_321-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.321-b07, mixed mode)
scala -version
Scala code runner version 3.1.1 -- Copyright 2002-2022, LAMP/EPFL
Here is my steps to run the code, it works well on my environment.
- Save the following code to file
happyBirthday.scala
, note that I change return value type from String
to Unit
@main def happyBirthday(age: Int, name: String, others: String*) =
val suffix =
age % 100 match
case 11 | 12 | 13 => "th"
case _ =>
age % 10 match
case 1 => "st"
case 2 => "nd"
case 3 => "rd"
case _ => "th"
val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name")
for other <- others do bldr.append(" and ").append(other)
println(bldr.toString)
- just run scala file in terminal
$ scala happyBirthday.scala 23 Lisa Peter
Happy 23rd birthday, Lisa and Peter
If I just run scala happyBirthday 23 Lisa Peter
, it will rasie java.lang.ClassNotFoundException: happyBirthday
since I haven’t compiled it.
And after compile scalac happyBirthday.scala
$ ls
happyBirthday$package$.class happyBirthday$package.tasty happyBirthday.scala
happyBirthday$package.class happyBirthday.class happyBirthday.tasty
And re-run
$ scala happyBirthday 23 Lisa Peter
Happy 23rd birthday, Lisa and Peter
It also works.
My environment:
$ java -version
openjdk version "11.0.9.1" 2020-11-04
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9.1+1)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9.1+1, mixed mode)
$ scala -version
Scala compiler version 3.0.0 -- Copyright 2002-2021, LAMP/EPFL
$ sw_vers
ProductName: macOS
ProductVersion: 12.1
BuildVersion: 21C52
1 Like
Compiling your code gives me 13 |println(bldr.toString) |Illegal start of toplevel definition
@yarchik does your editor ever set up something similar automatic indentation?
Here is my result.
It seems something different in your enviroment.
The reason of java.lang.NumberFormatException
, I guess , is that the input string happyBirthday
has be regarded as age
, and the string happyBirthday
can not convert to Int
type.
First of all I was confused about the indentation, I thought it is not strict. After correcting it I could compile, but get the same problem when I run the code. Any idea how to debug?
By the way, it works now without compiling scala happyBirthday.scala 23 Lisa Peter
. The compiled version is still not working. I checked many times.
@yarchik It’s great you are testing these! Scala 3 documentation is still very much a work in progress so it will have issues.
Please consider reporting some of your findings to improve the documentation!
Contributing to the Docs | Scala 3 Documentation | Scala Documentation
I agree! The new user experience is the hardest problem in computer science because after you’ve solved naming, cache invalidation, and off by one, The new user experience is the hardest problem in computer science.
Sorry for the glitch.
One can’t say to someone trying to compile and run happy birthday that you’re supposed to start with hello, world and work your way up.