問題は、コードがコンパイル時と実行時の概念を混在させることです。
あなたが使用している "list"変数はコンパイル時の値です(つまり、コンパイル時に反復されることになっています)。そして、実行時まで保持するように要求しています値)。このクロスステージの難点はいわゆるフリータームの作成につながる。
簡潔に言えば、フリーの用語は、前の段階の値を参照するスタブです。
val free$x1 = newFreeTerm("x", staticClass("scala.Int").asTypeConstructor, x);
Ident(free$x1)
賢い、ハァッを:たとえば、次のコード:以下のように
val x = 2
reify(x)
は、コンパイルされますか?結果は、xがIdentであり、型(コンパイル時の特性)を保持しますが、それにもかかわらずその値(実行時特性)も参照するという事実を保持します。これは、語彙的なスコープによって可能になる。
しかし、このツリーを(マクロの呼び出しサイトにインライン展開された)マクロ展開から戻そうとすると、事態が爆発します。マクロの呼び出しサイトは、そのレキシカルスコープではxをほとんど持たないため、xの値を参照することはできません。
さらに悪いのは何ですか?上記のスニペットがマクロの中に書かれている場合、xはコンパイル時にのみ、つまりコンパイラを実行するJVMにのみ存在します。しかし、コンパイラが終了すると、それはなくなりました。
しかし、xへの参照を含むマクロ展開の結果は、実行時に(おそらく、別のJVMで)実行されるはずです。これを理解するには、クロスステージ永続性、つまり、任意のコンパイル時の値を何らかの形でシリアル化し、実行時にデシリアライズする機能が必要です。私はScalaのようなコンパイル言語でこれを行う方法を知らない。
いくつかのケースでは、クロスステージ持続性が可能であることに注意してください。xは静的オブジェクトのフィールドだった場合たとえば、:
object Foo { val x = 2 }
import Foo._
reify(x)
そして、それは自由な用語として終わるませんが、簡単な方法で具体化されるだろう:
Select(Ident(staticModule("Foo")), newTermName("x"))
ですScala Days 2012でのSPJの講演でも議論された興味深い概念です:http://skillsmatter.com/podcast/scala/haskell-cloud。
いくつかの式に自由語が含まれていないことを確認するために、Haskellでは、コンパイラに新しい組み込みプリミティブ、型コンストラクタStatic
を追加します。マクロでは、reify(それ自体は単なるマクロ)を使って自然に行うことができます。ここでの説明を参照:https://groups.google.com/forum/#!topic/scala-internals/-42PWNkQJNA。
さて、元のコードの問題点を確認しました。どのように機能させるのですか?
reifiedはダイナミックなツリーを表現するのに苦労しているため、残念ながら手作業でASTを作成する必要があります。マクロロジーでのReifyの理想的な使用例は、マクロコンパイル時に知られている穴の種類を持つ静的テンプレートを持つことです。脇に歩いてください。手で木を建てることに頼らざるを得ません。
ボトムラインは、あなたが(:http://groups.google.com/group/scala-language/browse_thread/thread/bf079865ad42249cを正確に変更されているものを見るためにScalaの言語での移行ガイドを参照してください、最近リリース2.10.0-M4で動作します):次のように行かなければならないということです
import scala.reflect.makro.Context
object Macros {
def join_impl(c: Context)(a: c.Expr[Int]): c.Expr[List[Int]] = {
import c.universe._
import definitions._
a.tree match {
case Block(list, ret) =>
c.Expr((list :+ ret).foldRight(Ident(NilModule): Tree)((el, acc) =>
Apply(Select(acc, newTermName("$colon$colon")), List(el))))
}
}
def join(a: Int): List[Int] = macro join_impl
}
スカラー2.11でもっと簡単なことがありますか?準引用符が役立つでしょうか? (私は深いところでマクロを勉強していませんが、私が試してみるといつもこれにぶつかります) – HRJ
Quasiquotesは少し助けてくれるでしょう:https://gist.github.com/densh/6209261 –