2016-09-15 16 views
1

ブラックボックスマクロからfor yieldブロックを放出しようとすると、私はあなたが有効な構文でブロックを作成することができます方法を理解するために失敗してるから内包のために発行してください。このブロックは後でマッチングPARAM名を有することになるメソッド内に挿入されるようにsource以下Scalaのマクロ:マクロ

は、ハードコードPARAM名です。 paramscase classフィールドを囲む、ちょうどparams: Seq[c.universe.ValDef]です。

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という形式のケースクラスのすべてのフィールドは、for comprehensionが成功した場合、同じcaseクラスインスタンスを返す抽出器のセットに変換されます。

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

問題がための内部を引用することにしてい:

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

Extractがちょうど型クラスであるとExtract.apply[T : Extract]だけでimplicitly[Extract[T]]が結合したコンテキストをマテリアライズされた場合、次のようにマクロ変換されます式を出力し、ブロックa <- bを出力します。

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

エラーが自身でScalaの無効でかなり明白a <- bようである、';' expected but '<-' foundです。上記のように表現ブロックを生成し準直交化する正しい方法は何ですか?

答えて

2

Hereはquasiquotesのすべての異なる種類の一覧です。 あり、あなたがfq補間を必要とするa <- b構文を表現することを見ることができます。 だからコードは、おそらくになります:

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