I'm completely baffled by the following behavior of macros:
The problem: I'm trying to write a query engine for a model built on case classes
, where the user only has to specify the fields against which he wishes to match.
The current approach: Currently, I'm doing the lazy thing and just exploiting default Scala pattern matching, using a macro to create the appropriate match
statement. The code is the following:
// This is the macro code, defined in project `macros`
import scala.reflect.macros.whitebox
object QueryEngineMacros {
import scala.language.experimental.macros
def cimpl(c: whitebox.Context)(cs: c.Expr[CallSite], q: c.Expr[String]): c.Tree = {
import c.universe._
val pattern = cq"$q => true"
q"""$cs match {
case ${pattern}
case _ => false
}"""
}
def coincides(cs: CallSite, q: String): Boolean = macro cimpl
}
// This is the engine code, defined in project `queries` (depends on `macros`)
object QueryEngine {
def apply(q: String, res: ExtractionResult): Seq[CallSite] =
res.callSites.filter(cs => QueryEngineMacros.coincides(cs, q))
}
The error: This is my first time using Scala macros, but everything seems fine. It doesn't complain about dependencies either. However, I get this error message:
Error:(27, 66) type mismatch;
found : String
required: some.package.CallSite
res.callSites.filter(cs => QueryEngineMacros.coincides(cs, q))
Does anybody know what could be the cause of this?
EDIT: Typo fix
Sorry but Scala Macros just don't work this way. Yes Scala macros can generate new code but they are run at the compile time. But what you seemingly want is to generate some code in runtime depending on the parameter q
you pass to the macro. This is impossible. Particularly the line
val pattern = cq"$q => true"
does not what you expect it to do. What you macro is actually generates is roughly following:
def apply(q: String, res: ExtractionResult): Seq[CallSite] =
res.callSites.filter(cs => cs match {
case q => true
case _ => false
})
So you try to match cs
of type CallSite
against q
of type String
(not the q
interpreted as a piece of code!) ie you effectively check if cs
is equal to q
and the compiler sees that this match is just never true and says this to you in the error.
To sum up: if your q
is actually a compile time constant, such macro provides almost no benefits. And if it is a runtime variable - such macro just want help at all.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.