4

私の質問は不自然かもしれません。推奨されるものではなく、実現可能性の証明以上のものと考えたいと思います。コンテキストを説明するために、組み込み DSL に次の構文とは異なる構文を持たせようとします。

val myVal = "someContent"

私はそのようなことをしたいと思います:

assign("SomeContent","someVariable") => converted to
someVariable = "SomeContent"

コードの後半で、変数が使用可能になります。通常、REPL には次のようなものがあります。

assign("John","name")
println("Hello " + name)

私はそのトリックを行うためにマクロ (または ScalaCompiler プラグインですが、ここではさらに複雑だと思います) を考えてきました。まず、これがマクロの初心者であるために実現可能かどうかはわかりません。

String のみを操作することを考慮して、単純化したものから始めました。次のようなものから始めました。

def assign(content: String, targetVal: String):Unit = macro assignMacro

def assignMacro(c:Context)(content: c.Expr[String], 
                           targetVal: c.Expr[String]):c.expr[Unit] = {
  import c.universe._

  c.Expr[Unit](ValDef(Modifiers(), TermName(targetVal.value),
                      TypeTree(), Literal(Constant(content.value)))
}

残念ながら、いくつかの間違いのために失敗しているようです

  • 最初に、新しい用語名を作成しようとすると、式の eval を呼び出す必要があると確信している場合に提案されます。残念ながら、よくわかりません;)試してみると、失敗します;)
  • この targetVal と content を myVal や myContent などの定数に置き換えると、compiler found and required Unit のような 2 番目のエラー メッセージが表示されます

私は少し立ち往生しています。まずこれは可能ですか?はいと思います;)そして、どうすればこれを達成できますか?

助けてくれてありがとう

よろしくお願いします

4

1 に答える 1

3

2.10 と 2.11 の両方で、def マクロはブロックに展開されます。これは、それらが導入する定義がそのブロックに対してローカルになることを意味します。これはマクロの楽園で変わる可能性がありますが、いつ、どのように変わるかはわかりません。

現時点では、Scala のマクロは新しい変数を既存のスコープに透過的に導入する方法を提供していません。これは、Scala マクロの進化の歴史的な成果であり、リフレクション グループがブラックボックス マクロ (通常のメソッドのように動作し、型シグネチャによって完全に記述されたマクロ) を優先したため、人間とプログラムはその実装を欠落することなくブラック ボックスとして扱うことができます。何でも出します)。

ホワイトボックス マクロ (ブラックボックス スキームに適合しないマクロ) への最近の関心により、いくつかの結果が得られましたが、これらの結果はメインラインの Scala にはまだ含まれていません。この問題については、明日の Strange Loop での講演で詳しく説明します: https://thestrangeloop.com/sessions/evolution-of-scala-macros


それまでの間、探している自由度を提供する可能性のあるマクロ注釈を調べることができます。たとえば、mydsl注釈を適切に定義することで、

@mydsl 
def foo = {
  assign("SomeContent", "someVariable")
  ...
}

に変身

def foo = {
  someVariable = "SomeContent"
  ...
}
于 2013-09-18T04:52:21.957 に答える