3

Symbolマクロを使用して、ケース クラス データ ツリーのフィールドとサブフィールドの sを参照するための一般的なソリューションを取得したいと考えています。

この要点に触発されて、次のスケルトンを作成しました。

import language.experimental.macros
import reflect.runtime.universe._
import reflect.macros.Context

object SubRef {

  case class SubRef[ SourceT, TargetT ]( symbol : Symbol )

  implicit def functionToSubRef
    [ SourceT, TargetT ]
    ( f : SourceT => TargetT ) 
    : SubRef[ SourceT, TargetT ]
    = macro functionToSubRefMacro[ SourceT, TargetT ]

  def functionToSubRefMacro
    [ SourceT : c.WeakTypeTag, TargetT : c.WeakTypeTag ]
    ( c : Context )
    ( f : c.Expr[ SourceT => TargetT ] )
    : c.Expr[ SubRef[ SourceT, TargetT ] ]
    = ???

}

このソリューションは次のように機能することを期待しています。

case class A( b : B )
case class B( c : Int )

val ref : SubRef[ A, Int ] = _.b.c

渡された関数が次の場合、マクロ変換は失敗するはずです。

  • 単一の式ではありません
  • ソースシンボルのサブフィールドであるシンボルの値を返しません。targetSymbol.owner[.owner...] == sourceSymbol

欠落しているマクロの実装は何ですか?

4

1 に答える 1

2

Simon が指摘したように、2.10 では表記法が機能しないという事実を除けば、このマクロの作成は簡単なはずです。バリデーションのやり方は既にご存知のようですので、その部分は割愛します。

ここでの本当の課題は、コンパイル時のリフレクション アーティファクト ( c.universe.Symbol) を実行時のリフレクション アーティファクト ( ) に変換することru.Symbolです。これは具象化によって行うことができます。ツリーと型に対してこれを行うとが既にありますがc.reifyTree、まだ存在しません。c.reifyTypec.reifySymbol

幸いなことに、シンボルの具体化は非常に簡単に実装できるはずです。Ident(sym)シンボルをIdent でラップするだけc.reifyTreeです。次に、実行時にラッピング ツリーからシンボルを抽出するだけで完了です。

PS 現時点では、これらすべてのことを行うコードを書く時間がありません。あなたの誰かがマクロを実装してコードを投稿した場合、私は喜んで私の答えを削除し、あなたに賛成します:)

于 2013-03-12T10:27:59.100 に答える