Functions: Scala 3 Main Methods

Introduction: @main methods

  • They are the entry point to your Scala 3 application
  • This is different from Scala 2 approach
  • You can specify the command-line arguments you expect
  • Can still use the Scala 2 approach of a main method in an object
  • Note: We’re at a transition point between scalac/scala and scala-cli

Basic “Hello, world” example

@main def hello(): Unit =
    println("Hello, world")

Compile and run in one step with scala-cli:

scala-cli Hello.scala

Compile and run in two steps with scala-cli:

scala-cli compile Hello.scala
scala-cli run Hello.scala

The older approach:

scalac Hello.scala
scala hello

Handling command-line parameters

@main def hello(name: String): Unit =
    println(s"Hello, $name")

@main def hello(name: String, age: Int): Unit =
    println(s"Hello, $name, who is $age years old")

// varargs
@main def hello(names: String*): Unit =
    names.foreach(name => println(s"Hello, $name"))

You may want to handle the inputs as strings and convert them manually:

import scala.util.control.Exception.*

// this is a toplevel function
def makeInt(s: String): Option[Int] =
    allCatch.opt(s.toInt)

@main def hello(name: String, _age: String): Unit =
    val ageOption = makeInt(s)
    ageOption match
        case None =>
            println(s"Hello, $name, I didn’t get your age.")
        case Some(age) =>
            println(s"Hello, $name, who is $age years old.")

@main is different than the Scala 2 approach

// scala 2
object Hello extends App {
    println("Hello, world")
}

// also scala 2
object Hello {
    def main(args: Array[String]): Unit =
        println("Hello, world")
}

// can still do this in Scala 3
object Hello:
    def main(args: Array[String]): Unit =
        println("Hello, world")

More on scala-cli

When you have multiple Scala source code files in one directory, with only one @main method, run the entire project like this:

$ scala-cli .

Or, when you have multiple @main methods in one or more files in the same directory, when using scala-cli:

// MultipleMains.scala, multiple @main methods
@main def hello1(): Unit = println("Hello v1")
@main def hello2(): Unit = println("Hello v2")

Try to run them like this:

$ scala-cli MultipleMains.scala

[error]  Found several main classes: hello1, hello2
You can run one of them by passing it with the --main-class option, e.g.
  scala-cli MultipleMains.scala --main-class hello1

You can pick the main class interactively by passing the --interactive option.
  scala-cli MultipleMains.scala --interactive

As shown, that fails, but it shows that you run hello1 like this:

$ scala-cli MultipleMains.scala --main-class hello1