2017-03-15 3 views
0

私は複雑なコンパイル時のリフレクションに取り組んでおり、ASTを使用して手動でScalaコードを作成する必要があります。私は実際に私には意味をなさない奇妙なコンパイルエラーに気づいたので、テストプロジェクトでそれを再現することを試みました。コードがReefなしで作成されたときにScalaマクロがコンパイルされない

Scala 2.10.4を使用します。

ここでは、コードです:

Macro.scala:

object Macro { 
    def reifyTestImpl(c: Context): c.Expr[OffsetDateTime] = { 
    import c.universe._ 
    val expression = reify(OffsetDateTime.now()) 
    c.echo(c.enclosingPosition, "With reify: " + show(expression.tree)) 
    c.echo(c.enclosingPosition, "With reify (raw): " + showRaw(expression.tree)) 
    expression 
    } 

    def manualAstTestImpl(c: Context): c.Expr[OffsetDateTime] = { 
    import c.universe._ 
    val odtSymbol = typeOf[OffsetDateTime].typeSymbol 
    val now = newTermName("now") 
    val expression = c.Expr(
     Apply(
     Select(Ident(odtSymbol), now), 
     List() 
    ) 
    ) 
    c.echo(c.enclosingPosition, "Manual:  " + show(expression.tree)) 
    c.echo(c.enclosingPosition, "Manual (raw):  " + showRaw(expression.tree)) 
    expression 
    } 

    def reifyTest = macro reifyTestImpl 
    def manualAstTest = macro manualAstTestImpl 
} 

Tester.scala:

object Tester { 
    def main(args: Array[String]): Unit = { 
    println(Macro.reifyTest) 
    println(Macro.manualAstTest) 
    } 
} 

c.echoからの出力は次のとおりです。

With reify: OffsetDateTime.now() 
With reify (raw): Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List()) 
Manual:  OffsetDateTime.now() 
Manual (raw):  Apply(Select(Ident(java.time.OffsetDateTime), newTermName("now")), List()) 

コンパイルが私はMacro.manualAstTestへの呼び出しでvalue now is not a member of java.time.OffsetDateTimeを取得するエラーが発生します。
エコーからの出力が示唆するように、2つの式は同じですが、一方は動作し(reifyの式)、もう一方は動作しません(apply-selectで作成された式)。

2つの違いは何ですか?

答えて

0

犯人を見つけるために管理されます。
明らかにtypeOf[OffsetDateTime].typeSymbolは、スカラクラスから返されたシンボル、つまり静的メンバーがないシンボルを返します。 .companionSymbolを追加

は(名前が示すように...)それは静的メンバーのみで、である、Scalaのオブジェクトから返されただろうとして、シンボルを返すように思わ

したがって、次の変更は、それが動作します:

val odtSymbol = typeOf[OffsetDateTime].typeSymbol.companionSymbol 
関連する問題