0

Macro Paradiseの Eugene Burmako のマクロ注釈の例を使用し(Eugene に感謝します!)、ここでそれを変更しvalて、空のクラスhereに a を追加しました。

例として、期待どおり new を呼び出すことができますval。しかし、たとえばSalat (Scala sig を解析) やScalavro (2.10 リフレクションを使用) などで、更新されたクラスを型パラメーターとして使用しようとすると、クラスはまだ空に見えます (つまり、valが追加されていないかのように)。

Salat は Scala の署名を解析するので、確認したところ、通常の署名よりも 30 エントリほど短く、エントリの順序が異なります。それでも、署名には、追加された に関する情報が含まれているようですval

では、なぜ新しい val 情報にアクセスできないのでしょうか。そうする方法はありますか? ご覧いただきありがとうございます。

4

1 に答える 1

1

テンプレートに val を追加するだけでは、自動的にコンストラクタ パラメータにはなりません。そのためには、コンストラクタ自体も調整する必要があります。幸いなことに、手動でツリーを構築する場合と比較して、このタスクを大幅に簡素化する準引用符があります。

case q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$body }" :: Nil =>
  val CASEACCESSOR = (1 << 24).toLong.asInstanceOf[FlagSet]
  val PARAMACCESSOR = (1 << 29).toLong.asInstanceOf[FlagSet]
  val helloMods = Modifiers(CASEACCESSOR | PARAMACCESSOR | DEFAULTPARAM)
  val helloVal = q"""$helloMods val x: String = "hello macro!""""
  q"$mods class $name[..$tparams](..$first, $helloVal)(...$rest) extends ..$parents { $self => ..$body }"

いくつかの癖に注意してください: 1) Salat でのクラッシュを回避するために、公式 API には存在しない CASEACCESSOR および PARAMACCESSOR フラグを設定する必要があります。2) scalac がデフォルトを認識できるようにするために、DEFAULTPARAM を設定する必要があります。パラメーターをデフォルトとして、3) デフォルトのパラメーターはその型を推測できないため、ここで String を明示的に指定する必要があります。

于 2013-11-01T02:44:12.710 に答える