簡體   English   中英

使用Scala宏無法解釋的類型不匹配

[英]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類型的csString類型q (而不是q解釋為一段代碼!)進行匹配,即,您有效地檢查cs是否等於q ,並且編譯器看到此匹配永遠都不是真的,並說這給你的錯誤。

總結:如果您的q實際上是一個編譯時間常數,那么這種宏幾乎沒有任何好處。 而且,如果它是一個運行時變量,那么此類宏將只需要幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM