Jake
Jake

Reputation: 757

Introducing variables named by user in a macro

So I want to define a macro that introduces a couple of variables as variable declarations such that the names are defined by the user of the macro.

Say that I want to be able to write something like the following.

foldOver(0)(hd, rest)(List(1, 2, 3)) {
  hd + rest
}

My first thought on how to do this was to make the variables parameters and manually inspect them in some way. I wound up toying with a definition like the following.

def foldOver[A, B](z : B)(next : A, acc : B)(lst : List[A])(f : B): B = macro foldOverImpl[A, B]
def foldOverImpl[A : c.WeakTypeTag, B : c.WeakTypeTag]
                (c: Context)
                (z : c.Expr[B])(next : c.Expr[A], acc : c.Expr[B])
                (lst : c.Expr[List[A]])
                (f : c.Expr[B]): c.Expr[B] = {
    import c.universe._
    (next, acc) match {
      case (TermName(nextName), TermName(accName)) => {
        c.Expr[B](q"""{
          <do whatever here>
        }""")
      }
      case otherwise => {
        throw new Exception("the 'next' and 'acc' variables must be term names")
      }
    }
}

but when I use the macro as shown at the top that gives me an error saying that it can't find those variable names in the program. Well it shouldn't, I want those to be declared inside the macro and not the containing context.

So, is there a way to receive names from users and use those to declare variables within a macro?

Upvotes: 1

Views: 84

Answers (1)

Eugene Burmako
Eugene Burmako

Reputation: 13048

It's impossible to do this in a def macro, because def macros require all their arguments to typecheck prior to expansion. Macro annotations don't have this restriction, but they have different syntax that might be inappropriate for your use case.

Upvotes: 1

Related Questions