[英]Inexplicable type mismatch using Scala macros
我完全對以下宏行為感到困惑:
問題:我正在嘗試為基於case classes
構建的模型編寫查詢引擎,其中用戶只需指定他希望匹配的字段即可。
當前的方法:目前,我正在偷懶,只是利用默認的Scala模式匹配,使用宏來創建適當的match
語句。 代碼如下:
// 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))
}
錯誤:這是我第一次使用Scala宏,但是一切似乎都很好。 它也不抱怨依賴關系。 但是,我收到此錯誤消息:
Error:(27, 66) type mismatch;
found : String
required: some.package.CallSite
res.callSites.filter(cs => QueryEngineMacros.coincides(cs, q))
有人知道這可能是什么原因嗎?
編輯:錯字修復
抱歉,但是Scala Macros不能這樣工作。 是的,Scala宏可以生成新代碼,但是它們在編譯時運行。 但是,您似乎想要的是根據傳遞給宏的參數q
在運行時生成一些代碼。 這是不可能的。 特別是線
val pattern = cq"$q => true"
不符合您的期望。 您的宏實際生成的內容大致如下:
def apply(q: String, res: ExtractionResult): Seq[CallSite] =
res.callSites.filter(cs => cs match {
case q => true
case _ => false
})
因此,您嘗試將CallSite
類型的cs
與String
類型q
(而不是q
解釋為一段代碼!)進行匹配,即,您有效地檢查cs
是否等於q
,並且編譯器看到此匹配永遠都不是真的,並說這給你的錯誤。
總結:如果您的q
實際上是一個編譯時間常數,那么這種宏幾乎沒有任何好處。 而且,如果它是一個運行時變量,那么此類宏將只需要幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.