Skip to content

ioMain annotation for blazing fast getting started experience (Scala 3.2+) #3149

Open
@keynmol

Description

@keynmol

How'd you like them buzzwords.

Scala 3.2 added an experimental support for custom @main annotations, see here: https://dotty.epfl.ch/docs/reference/experimental/main-annotation.html#

It would be excellent to experiment with a @ioMain annotation (or even @io?) in Cats Effect or any auxiliary project.

I went ahead and wrote a demonstrator to hwet your appetite:

//> using scala "3.3.1"

//> using lib "org.typelevel::cats-effect::3.5.3"

import scala.annotation.MainAnnotation
import scala.util.CommandLineParser.FromString
import scala.annotation.experimental
import cats.effect._

@experimental class ioMain extends MainAnnotation[FromString, IO[Unit]]:
  import MainAnnotation.{Info, Parameter}

  def command(info: Info, args: Seq[String]): Option[Seq[String]] =
    Some(args)

  def argGetter[T](
      param: Parameter,
      arg: String,
      defaultArgument: Option[() => T]
  )(using parser: FromString[T]): () => T =
    () => parser.fromString(arg)

  def varargGetter[T](param: Parameter, args: Seq[String])(using
      parser: FromString[T]
  ): () => Seq[T] =
    () => args.map(arg => parser.fromString(arg))

  def run(program: () => IO[Unit]): Unit =
    val app = new IOApp.Simple {
      def run = program()
    }
    app.main(Array.empty)
end ioMain

@experimental
@ioMain def sum(first: Int, second: Int, rest: Int*) =
  IO.println(first + second + rest.sum)

Run this program with Scala CLI:

$ scli ioMain.scala -- 25 16 100 50

Once the annotation design exits experimental phase, users should just be able to do

@ioMain def sum(first: Int, second: Int, rest: Int*) =
  IO.println(first + second + rest.sum)

And enjoy that deliciously non-invasive experience.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions