I'm just experimenting with Scala macros, and I have some questions.
As a learning exercise, I was trying to write a Scala version of the Clojure macro on this StackOverflow reply: http://stackoverflow.com/a/10435150/179675 , which gives Clojure a C-style "for (a; b; c) ... " loop.
More specifically, that sample defines a macro that takes four (not three) arguments. The first two arguments are sym (the name of a new loop variable to define, which will be local to the loop), and init (its initial value). The other two arguments are check (the second expr in the for parens) and change (the third expr).
The part I can't figure out how to do is sym. The point is that at the point where I am invoking the macro, the variable does not yet exist. The macro is supposed to define it.
In other words, in the end, I want to be able to write some code like this:
// Note, 'i' has not yet been defined above this code
MyMacros.forloop(i, 0, i<10, i++) {
println(i)
}
I can't figure out how to do it. All I have so far is an empty macro definition:
object MyMacros {
def forloop(sym: Any, init: Any, check: Boolean, change: Any)
(loop: Any): Unit = macro forloopImpl
def forloopImpl(c: Context)(sym: c.Expr[Any],
init: c.Expr[Any],
check: c.Expr[Boolean],
change: c.Expr[Any])
(loop: c.Expr[Any]): c.Expr[Unit] = {
import c.universe._
reify {
}
}
}
That compiles fine, not surprisingly. Then I have an attempt (in a separate .scala file of course) to invoke it, which looks exactly like my first code sample above.
But when I compile the second file, I get this:
scalac -classpath bin -d bin MacroTest.scala
vi mymac MacroTest.scala:9: error: not found: value i
MyMacros.forloop(i, 0, i<10, i++) { println(i) }
^
one error found
make: *** [bin/MacroTest.class] Error 1
Since the compiler can't find i (which of course has not yet been defined), it complains.
One thing I tried, on a lark, was to make sym a pass-by-name variable:
def forloop(sym: => Any, init: Any, check: Boolean, change: Any)
(loop: Any): Unit = macro forloopImpl
...
But that resulted in a segmentation fault from the compiler :) (I am using scalac 2.10.0)
Any thoughts?