Depends on the meaning of "use". In principle you can use a macro (hello
) in another method (foo
) in the same file if you make the 2nd method a macro too (the 1st method call must be inside a quasiquote q"..."
, not reify{...}
)
import scala.language.experimental.macros
import scala.reflect.macros.blackbox // libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value
object Macros {
def hello(): Unit = macro hello_impl
def hello_impl(c: blackbox.Context)(): c.Expr[Unit] = {
import c.universe._
reify {
println("Hello World!")
}
}
}
object Main {
def foo(): Unit = macro fooImpl
def fooImpl(c: blackbox.Context)(): c.Tree = {
import c.universe._
q"Macros.hello()"
}
}
https://scastie.scala-lang.org/DmytroMitin/rom8yKvmSUGVk0GwtGzKqQ
The problem is that runnable def main(args: Array[String]): Unit
can't be a macro.
Another option is reflective toolbox. A macro can't be defined with toolbox (actual compiler is needed for that)
import scala.reflect.runtime
import scala.reflect.runtime.universe.Quasiquote
import scala.tools.reflect.ToolBox // libraryDependencies += scalaOrganization.value % "scala-compiler" % scalaVersion.value
val rm = runtime.currentMirror
val tb = rm.mkToolBox()
tb.compile(q"""
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
def bar(): Unit = macro barImpl
def barImpl(c: Context)(): c.Tree = {
import c.universe._
EmptyTree
}
""")
//macro implementation reference has wrong shape. required:
//macro [<static object>].<method name>[[<type args>]] or
//macro [<macro bundle>].<method name>[[<type args>]]
But a macro can be run in the same file using toolbox
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object Macros {
def hello(): Unit = macro hello_impl
def hello_impl(c: blackbox.Context)(): c.Expr[Unit] = {
import c.universe._
reify {
println("Hello World!")
}
}
}
import scala.reflect.runtime
import scala.reflect.runtime.universe.Quasiquote
import scala.tools.reflect.ToolBox
object Main {
def main(args: Array[String]): Unit = {
val rm = runtime.currentMirror
val tb = rm.mkToolBox()
tb.eval(q"Macros.hello()")
}
}
// Hello World!
https://scastie.scala-lang.org/DmytroMitin/rom8yKvmSUGVk0GwtGzKqQ/5
Regarding Codeforces the issue is that the compiler must be in classpath and calls via toolbox are comparatively slow.
Possible to identify/use Scala macros using reflection or similar? (Scala 3)