SQLのような抽象化をいくつか構築しようとしていて、問題が発生しました。マクロ計算の結果を実行時に渡すには、どのような方法が推奨されますか?
これは簡略化され、「データベーステーブル」である:
trait Coffee {
def id: Long
def name: String
def brand: String
}
これは私のクエリの抽象化である:
import language.experimental.macros
object Query {
def from[T] =
macro QueryMacros.fromMacro[T]
}
class From[T] {
def select[S](s: T => S): Select[T] =
macro QueryMacros.selectMacro[T, S]
}
class Select[T] {
def where(pred: T => Boolean): Where =
macro QueryMacros.whereMacro[T]
}
class Where(val result: String)
これは私のマクロ実装です:
import scala.reflect.macros.Context
object QueryMacros {
val result = new StringBuilder
def fromMacro[T : c.WeakTypeTag](c: Context): c.Expr[From[T]] = {
result ++= ("FROM " + c.weakTypeOf[T])
c.universe.reify(new From[T])
}
def selectMacro[T : c.WeakTypeTag, S : c.WeakTypeTag](c: Context)(s: c.Expr[T => S]): c.Expr[Select[T]] = {
result ++= ("SELECT " + s.tree)
c.universe.reify(new Select[T])
}
def whereMacro[S](c: Context)(pred: c.Expr[S]): c.Expr[Where] = {
result ++= ("WHERE " + pred.tree)
c.universe.reify(new Where(result.toString))
}
}
そして、これは私ですサンプルコード:
object Main extends App {
println("Query start")
val query =
Query.from[Coffee]
.select(_.id)
.where(_.brand == "FairTrade")
println(query.result)
println("Query end")
}
これは、コンパイルし、細かい動作しますが、出力は次のとおりです。
Query start
Query end
基本的には、result
は空のようです。私はそれが木の蓄積された糸を保持すると予想した。
にはどうすれば次のステージにマクロコンパイル段階から自分のデータを渡すことができ、それは、実行時に現れますか? もちろん、現在の文字列を明示的に次のメソッドに渡すことはできますが、私はそれを避けたいと思います。
こんにちはユージーン、ありがとう、私は見ていきます。 1つの真の解決策があるように見えます。 :-) – soc