2016-09-15 84 views
1

嘗試從黑盒宏發出for yield塊,但我無法理解如何使用有效的語法創建塊。Scala宏:從宏指令中排除

因此低於source是一個硬編碼的參數名稱,因爲此塊稍後將插入到具有匹配參數名稱的方法中。 params只是params: Seq[c.universe.ValDef],內附case class字段。

def extract(source: Source): Option[CaseClass] = { ... } 

val extractors = accessors(c)(params) map { 
    case (nm, tpe) => { 
    val newTerm = TermName(nm.toString + "Opt") 
    q"""$newTerm <- DoStuff[$tpe].apply("$nm", source)""" 
    } 
} 

val extractorNames = accessors(c)(params) map { 
    case (nm, tpe) => TermName(nm.toString + "Opt") 
} 

這基本上是採取case class,並輸出一個用於產黑到基本上重新從理解的情況下類。

形式爲name: Type的case類中的每個字段都被轉換爲一組提取器,如果for理解成功,則返回相同的case類實例。

case class Test(id: Int, text: String) 

公司將宏轉化爲以下,其中Extract僅僅是一個類型的類和Extract.apply[T : Extract]只是物化與implicitly[Extract[T]]結合的上下文:

for { 
    idOpt <- Extract[Int].apply("id", source): Option[Int] 
    textOpt <- Extract[String].apply("text", source): Option[String] 
} yield Test(idOpt, textOpt) 

,問題就在具有引用內爲生成表達式並輸出a <- b塊。

def extract(source: Source): Option[$typeName] = { 
    for {(..$extractors)} yield $companion.apply(..$extractorNames) 
} 

的錯誤是';' expected but '<-' found,這是很明顯的a <- b無效斯卡拉本身。生成和準表達式塊的正確方法是什麼才能使上述方法起作用?

回答

2

Here是所有不同種類quasiquotes的列表。 在那裏您可以看到,要表達a <- b語法,您需要fq插值器。 這樣的代碼可能會變成:

val extractors = accessors(c)(params) map { 
    case (nm, tpe) => { 
    val newTerm = TermName(nm.toString + "Opt") 
    fq"""$newTerm <- DoStuff[$tpe].apply("$nm", source)""" 
    } 
} 

然後與正常插值:

q"for (..$extractors) yield $companion.apply(..$extractorNames)" 
+0

沒錯發現它在平均時間,這是一個。非常感謝! – flavian

+0

忘記添加'{}'包裝是沒有必要的,編譯器不喜歡它們。 '()'就夠了。只要修改誰就會在未來找到答案。 – flavian