2

Given scala version 2.11.7 and this macro definition:

import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
package object macrotest {
  def namedMacro(c: Context)(a: c.Expr[Int]): c.Expr[Int] = {
    println("the int expr was " + a)
    a
  }
  def named(a: Int = 1) = macro namedMacro
}

And this invocation:

object NamedMacroTest {
  def main(args: Array[String]) {
    named()
    //named(a = 5) // or this
  }
}

Why do I see this error?

Error:(5, 10) macro applications do not support named and/or default arguments

And what can I do to not get the error, while still being able to call the macro with named and default arguments?

eirirlar
  • 814
  • 6
  • 24

1 Answers1

4

It was supposed to go back in, according to the 2.11 docs.

The original issue was addressed in this PR which details the challenges.

It was shot down finally at this attempt for technical reasons. They didn't like doing the desugaring and then losing what the original application looked like; and they didn't want to perform transforms and then have to undo it.

One idea is to let adaptation take over when the arg is omitted:

scala> :pa
// Entering paste mode (ctrl-D to finish)

def m[A: c.WeakTypeTag](c: Context)(i: c.Expr[A]): c.Expr[Int] = {
  import c.universe._
  if (i.tree.tpe <:< typeOf[Int]) i.asInstanceOf[c.Expr[Int]]
  else if (i.tree.tpe <:< typeOf[Unit]) c.Expr[Int](q"42")
  else c.abort(null,  "Nope") }

// Exiting paste mode, now interpreting.

m: [A](c: scala.reflect.macros.whitebox.Context)(i: c.Expr[A])(implicit evidence$1: c.WeakTypeTag[A])c.Expr[Int]

scala> def f[A](i: A): Int = macro m[A]
defined term macro f: [A](i: A)Int

scala> f(1)
res9: Int = 1

scala> f()
warning: there was one deprecation warning; re-run with -deprecation for details
res10: Int = 42

scala> f("")  // I don't remember where they keep NoPosition
java.lang.NullPointerException

It's easier just to do something different, like indirect through a method that takes an empty param list. Compare https://stackoverflow.com/a/25219644/1296806 and comments.

Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • Thanks. I like your approach with missing args, and the annotation solution you linked to also has use cases. You didn't address named args, but I guess that was something that was supposed to be solved with this: https://github.com/scala/scala/pull/3753 Strange - from the comments, it seems they just forgot about the whole pullrequest. From how I understand you, there's no way with current macros to implement something that looks like the case class copy method, and invoke it the same way it's invoked? – eirirlar Dec 08 '15 at 07:55
  • Just let the API act as an adaptor method (with defaults etc) that calls your internal method with all args supplied and ordered. It depends on if you were trying to do something quite tricky. – som-snytt Dec 08 '15 at 21:40
  • Yeah.. the thing is I wanted to try to make the macro impl detect if the client code passed the argument or if it was supplied by the default value. Guess I have to look for another way maybe an HMap or something. – eirirlar Dec 08 '15 at 23:47