5

この質問に答えて、私はマクロパラダイスブランチを使用してScalaでHaskellスタイルの「where」式を実装しようとしています。コードはscala-whereで入手できます。これで、次のように書くことができます。

val result = where ( f1(1) * f2(2), {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
})

しかし、私が本当にやりたいのは、これを中置位置で呼び出すことができるようにすることです。

val result = ( f1(1) * f2(2)) where {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
}

通常、この種のことは簡単ですが、マクロ呼び出しでそれを行う方法がわかりません。式(f1(1)* f2(2))は、マクロアプリケーションの前に入力されないため、暗黙の値クラスを作成するようなものは機能しません。そうでなければ、この種の構文を取得する方法はありますか?

これに失敗した場合は、2つのパラメータリストを作成するだけで、次のことが可能になります。

val result = where (f1(1) * f2(2)) {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
}

いいのですが、これも難しいようです。2つのパラメータリストを持つマクロを呼び出すことはできますか?

4

2 に答える 2

2

最初のオプションの場合: 暗黙的な変換を型指定されていないマクロ自体にすることができると思いますか?

2 番目のオプション: 複数のパラメーター リストを使用してマクロを呼び出すことができます。はい。呼び出しサイトの複数のリストは、定義サイトの複数のリストに変換されます。例:

def myMacro(a: _)(b: _) = macro myMacro_impl

def myMacro_impl(c: Context)(a: c.Tree)(b: c.Tree): c.Tree = { ... }

次のように呼び出されます。

myMacro(...)(...)
于 2013-03-06T19:05:41.283 に答える
1

回答: 2013 年 3 月 8 日現在、型指定されていないマクロを中置位置で使用することはできません。scala-user メーリング リストの Eugene Burmako から引用:

現在、暗黙的な解決が開始される前に、左側の引数を最初に型チェックする必要があります。「class foo(x: _)」と記述できるという事実は見落としです。アンダースコア構文は、型指定されていないマクロでのみ機能するはずです。

参考までに、これを行うことができるようになったのは次のとおりです。

implicit class HasWhere(val exp : _) {
 def where(block : Unit) = macro whereInfix
}

def whereInfix(c : Context)(block : c.Expr[Unit]) = {
  import c.universe._

  val exp = Select(c.prefix.tree, TermName("exp"))
  val Expr(Block((inner, _))) = block
  val newinner = inner :+ exp
  Block(newinner : _*)
}
于 2013-03-08T13:53:29.963 に答える