1

I am trying to make working an example from the scala docs: https://docs.scala-lang.org/overviews/macros/overview.html

I have two files:

object Main extends App {

  println("Testing assert macro...")
  val result = Asserts.assert(true, "abc")

}

and:

import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros

object Asserts {
  val assertionsEnabled: Boolean = true

  def assert(cond: Boolean, msg: Any): Unit = macro Asserts.assertImpl

  private def raise(msg: Any) = throw new AssertionError(msg)

  def assertImpl(c: Context)(cond: c.Expr[Boolean], msg: c.Expr[Any]) : c.Expr[Unit] = {
    import c.universe._
    if (assertionsEnabled)
      c.Expr(q"if (!cond) raise(msg)")
    else
      c.Expr(q"()")
  }
}

but I am getting an error:

Error:(8, 30) not found: value cond val result = Asserts.assert(true, "abc")

any idea how to make it working ? thanks!

FrancMo
  • 2,459
  • 2
  • 19
  • 39

1 Answers1

4

Macros and main code must be in different subprojects

https://www.scala-sbt.org/1.x/docs/Macro-Projects.html

You missed dollar signs ($cond, $msg instead of cond, msg), otherwise while the macro is expanded inside Main you're trying to use absent local variables cond, msg rather than splice parameters cond, msg of the macro. Also it must be known inside Main that raise is Asserts.raise so either use import Asserts.raise in Main or fully qualified name in the quasiquote. Try

c.Expr(q"if (!$cond) Asserts.raise($msg)")

Also Asserts.raise must be accessible inside Main so remove private.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66