4

ノードを作成するメソッドを定義しました。このメソッドtreeNodeは子ノードを持つことができます。簡略化されたコードは次のとおりです。

def treeNode(text:String) (children: => Any) {
    val b = new TreeNode(text)
    children
}

この方法を使用するときは、次のように書く必要があります。

treeNode("aaa") {
    treeNode("bbb") {}
    treeNode("ccc") {}
}

子を持たないリーフノードを確認できますが、空のブロックが必要{}です。

children: => Anyパラメータにデフォルトの何もしない値を与える方法はありますか?コードを次のように書くことができます:

treeNode("aaa") {
    treeNode("bbb")
    treeNode("ccc")
}

ヘルプ〜

4

2 に答える 2

9

問題は、何もしない(デフォルト)値を指定できないことではありません。問題は、たとえそうだとしても、複数のパラメーターブロックを持つ関数は、少なくとも各ブロックに括弧または中括弧を持たなければならないということです。

例外が1つあります。暗黙のパラメータブロックを参照する必要はまったくありません。残念ながら、名前による呼び出しの暗黙的なパラメーターを持つことは許可されていません。たとえそうだったとしても、署名により、ランダムな暗黙的なパラメーターがその場所で機能するようになります。

さて、これを回避する方法があります。これを完全にするために示しますが、(のように別の名前が必要なだけではないと仮定してleafNode)末尾をそのままにしておくことをお勧めします{}

次のようにすると、必要な構文を正確に取得できます。まず、暗黙のパラメーターが必要ですが、それをラッパークラスにします(Function0すでに存在するものを使用できますが、次のステップで意図しない結果が生じる可能性があります)。

trait AnyByName { def eval: Any }
def treeNode(text: String)(implicit children: AnyByName) = (text,children.eval)

ここで、2つのことが必要です。名前Anyを新しい特性に変換できる必要があります。また、暗黙的に何もしないものを使用できるようにする必要があります。だから私たちは

implicit val nameForDoingNothing = new AnyByName { def eval = () }
implicit def wrap_any_by_name(a: => Any) = new AnyByName { def eval = a }

そして今、私たちはあなたが求めていた行動を回復します:

scala> treeNode("Hi")
res1: (String, Any) = (Hi,())

scala> treeNode("Hi") { treeNode("there") }
res2: (String, Any) = (Hi,(there,()))

(あなたの例では、何も返しません。ここでは、それが機能することを示すために返します。)

ただし、一部のsを回避するためのツールはたくさんあります。そのため、これが非常に頻繁に使用されるDSLであり、2つの名前が受け入れられない{}と予想される場合にのみ、これを行うことをお勧めします。(また、それが非常に頻繁に使用されることを期待する場合は、おそらく名前としては痛いほど長いです;私はちょうど提案します。)treeNodenode

于 2012-01-08T11:24:05.767 に答える
6

AFAICTデフォルトでは、一種の空のブロックを渡すことはできません。

treeNodeところで、別の関数を作成することで、関数に基づいてタスクを簡単に分割できますdef leaf(text:String) = treeNode(t) {}

于 2012-01-08T10:49:00.750 に答える