Rogach
Rogach

Reputation: 27200

Is there a way to use by-value parameters in scala macros?

For example, I want to create a macro with this form:

def debug(fn: => Unit): Unit = if (doDebug) fn else ()

I tried the following:

def debug(fn: => Unit): Unit = macro debugImpl
def debugImpl(c: Context)(fn: c.Expr[Unit]): c.Expr[Unit] = {
  if (doDebug) fn else reify(())
}

but it fails with compilation error:

macro implementation has wrong shape:
  required: (c: scala.reflect.macros.Context)(fn: c.Expr[=> Unit]): c.Expr[Unit]
  found   : (c: scala.reflect.macros.Context)(fn: c.Expr[Unit]): c.Expr[Unit]
  type mismatch for parameter fn: c.Expr[=> Unit] does not conform to c.Expr[Unit]
    def debug(fn: => Unit): Unit = macro debugImpl

If I write the type of fn param as c.Expr[=> Unit], it obviously fails with compilation error.

I am using scala 2.10.2. Is there a way to achieve such a macro?

Upvotes: 1

Views: 219

Answers (1)

senia
senia

Reputation: 38045

You could use c.Expr[Any] and change the type of fn: c.Expr[Unit](fn.tree).

def debug(fn: => Unit): Unit = macro debugImpl
def debugImpl(c: Context)(fn: c.Expr[Any]): c.Expr[Unit] = {
  import c.universe.reify
  if (true) c.Expr[Unit](fn.tree) else reify(())
}


scala> debug( println("abc") )
abc

Upvotes: 2

Related Questions