|
| 1 | +--- |
| 2 | +layout: doc-page |
| 3 | +title: "Main Methods" |
| 4 | +--- |
| 5 | + |
| 6 | +Scala 3 offers a new way to define programs that can be invoked from the command line: |
| 7 | +A @main annotation on a method turns this method into an executable program. |
| 8 | +Example: |
| 9 | +```scala |
| 10 | + @main def happyBirthday(age: Int, name: String, others: String*) = { |
| 11 | + val suffix = |
| 12 | + (age % 100) match { |
| 13 | + case 11 | 12 | 13 => "th" |
| 14 | + case _ => |
| 15 | + (age % 10) match { |
| 16 | + case 1 => "st" |
| 17 | + case 2 => "nd" |
| 18 | + case 3 => "rd" |
| 19 | + case _ => "th" |
| 20 | + } |
| 21 | + } |
| 22 | + val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name") |
| 23 | + for other <- others do bldr.append(" and ").append(other) |
| 24 | + bldr.toString |
| 25 | + } |
| 26 | +``` |
| 27 | +This would generate a main program `happyBirthday` that could be called like this |
| 28 | +``` |
| 29 | +> scala happyBirthday 23 Lisa Peter |
| 30 | +Happy 23rd Birthday, Lisa and Peter! |
| 31 | +``` |
| 32 | +A `@main` annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main` method can have an arbitrary number of parameters. |
| 33 | +For each parameter type there must be an instance of the `scala.util.FromString` typeclass |
| 34 | +that is used to convert an argument string to the required parameter type. |
| 35 | +The parameter list of a main method can end in a repeated parameter that then |
| 36 | +takes all remaining arguments given on the command line. |
| 37 | + |
| 38 | +The program implemented from a `@main` method checks that there are enough arguments on |
| 39 | +the command line to fill in all parameters, and that argument strings are convertible to |
| 40 | +the required types. If a check fails, the program is terminated with an error message. |
| 41 | +Examples: |
| 42 | +``` |
| 43 | +> scala happyBirthday 22 |
| 44 | +Illegal command line after first argument: more arguments expected |
| 45 | +> scala happyBirthday sixty Fred |
| 46 | +Illegal command line: java.lang.NumberFormatException: For input string: "sixty" |
| 47 | +``` |
| 48 | +The Scala compiler generates a program from a `@main` method `f` as follows: |
| 49 | + |
| 50 | + - It creates a class named `f` in the package where the `@main` method was found |
| 51 | + - The class has a static method `main` with the usual signature. It takes an `Array[String]` |
| 52 | + as argument and returns `Unit`. |
| 53 | + - The generated `main` method calls method `f` with arguments converted using |
| 54 | + methods in the `scala.util.CommandLineParser` object. |
| 55 | + |
| 56 | +For instance, the `happyBirthDay` method above would generate additional code equivalent to the following class: |
| 57 | +```scala |
| 58 | + class happyBirthday { |
| 59 | + import scala.util.{CommndLineParser => CLP} |
| 60 | + <static> def main(args: Array[String]): Unit = |
| 61 | + try |
| 62 | + happyBirthday( |
| 63 | + CLP.parseArgument[Int](args, 0), |
| 64 | + CLP.parseArgument[String](args, 1), |
| 65 | + CLP.parseRemainingArguments[String](args, 2)) |
| 66 | + catch { |
| 67 | + case error: CLP.ParseError => CLP.showError(error) |
| 68 | + } |
| 69 | + } |
| 70 | +``` |
| 71 | +**Note**: The `<static>` modifier above expresses that the `main` method is generated |
| 72 | +as a static method of class `happyBirthDay`. It is not available for user programs in Scala. Regular "static" members are generated in Scala using objects instead. |
| 73 | + |
| 74 | +`@main` methods are the recommended scheme to generate programs that can be invoked from the command line in Scala 3. They replace the previous scheme to write program as objects with a special `App` parent class. In Scala 2, `happyBirthday` could be written also like this: |
| 75 | +```scala |
| 76 | + object happyBirthday extends App { |
| 77 | + // needs by-hand parsing of arguments vector |
| 78 | + ... |
| 79 | + } |
| 80 | +``` |
| 81 | +The previous functionality of `App`, which relied on the "magic" `DelayedInit` trait, is no longer available. `App` still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build |
| 82 | +between Scala 2 and Scala 3, it is recommende to use an explicit `main` method with an `Array[String] argument instead. |
0 commit comments