2

問題

この質問の動機は、この質問の解決策を見つけようとすることです。

次の構文を使用して階層構造を構築するとします。

root {
  subA {
    subB("b1.1")
    subB("b1.2")
  }
}

subB構築 DSL はタイプ セーフである必要があります。つまり、 aを に直接ネストrootしたり、 asubAを別の にネストしたりできませんsubA。したがって、私の考えは、 methodrootを定義するオブジェクトを返すメソッドを用意subAし、後者が を定義するオブジェクトを返すようにすることsubBです。

私が今欲しいのは、に渡されるコードのブロックroot、つまり、

  subA {
    subB("b1.1")
    subB("b1.2")
  }

の呼び出しがsubBによって作成されたオブジェクトにバインドされるように、 が実行されrootます。基本的にはこのように

root { r: Root =>
  r.subA { sa: SubA =>
    sa.subB("b1.1")
    sa.subB("b1.2")
  }
}

ただし、レシーバーrsa明示的にする必要はありません。

質問:this Scala ではコード ブロック内でレシーバー、特に暗黙のレシーバーを再バインドできますか? おそらくマクロを使用しますか?

その他のアプローチ

この記事では、似たような XML ツリーの構築 DSL について説明します。それらの実装は機能に基づいてDynamicおり、結果の DSL 構文は次のようになります。

xml html {
  xml head {
    xml title "Search Links"
  }
}

ただし、このアプローチには明示的なレシーバー (ここでは object ) が必要であり、さらに深刻なことに、ノードをノード内にxmlネストすることを静的に防止するという意味で、タイプセーフではないと思います。htmltitle

4

1 に答える 1

0

これが使えるかどうかはわかりませんが、あなたが書いたコードとよく似ています。andをandに追加,して変更しました。{}()

trait RootElement
trait SubAElement

def root(f:(() => RootElement)*) = ???
def subA(f:(() => SubAElement)*):() => RootElement = ???
def subB(s:String):() => SubAElement = ???

root(
  subA (
    subB("b1.1"),
    subB("b1.2")
  )
)

どのように使用したいのかわかりませんが、使用可能な場合は、ユースケースに基づいてより具体的なバージョンを試してみることができます.


編集

コードのブロック内でレシーバー、特に暗黙の this レシーバーを再バインドできますか?

いいえ、私が知る限り、すぐに使用できるわけではありません。おそらくマクロでそれを行うことができますが、私はそれを手伝うことはできません. マクロについての私の限られた知識は、それがかなりの冒険になることを教えてくれます。

マクロなしで同じ効果を得るために、小さな例を作成しました。より簡潔にするために怠惰を取り除きました。

class Root {
  def subA(subA: SubA) = {
    // do something with subA
  }
}

class SubA {
  def subB(s: String) = {
    // do something with subB
  }
}

case class RootElement(value: SubA)
case class SubAElement(value: String)

def root(rootElems: (RootElement)*): Root = {
  val r = new Root

  rootElems foreach { sub =>
    r.subA(sub.value)
  }
  r
}

def subA(subElems: SubAElement*): RootElement = {
  val sA = new SubA
  subElems foreach { sub =>
    sA.subB(sub.value)
  }
  RootElement(sA)
}

def subB(s: String): SubAElement = SubAElement(s)

root(
  subA(
    subB("b1.1"),
    subB("b1.2")
  )
)
于 2013-02-16T13:30:30.517 に答える