私はバイナリツリーの末尾の再帰的な折畳み関数を見つけようとしています。以下の定義を考える:Scalaのバイナリツリーのテールの再帰的な折り返し
def fold[A, B](t: Tree[A])(map: A => B)(red: (B, B) => B): B =
t match {
case Leaf(v) => map(v)
case Branch(l, r) =>
red(fold(l)(map)(red), fold(r)(map)(red))
}
しかし、今、私は、注釈@annotation.tailrec
を使用することができるように末尾再帰倍機能を見つけるのに苦労しています:
// From the book "Functional Programming in Scala", page 45
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
非末尾再帰関数の実装は非常に簡単です。
私の研究の中で、ツリー上のテールの再帰的な機能が次のようないくつかの例を見出しました。基本的にList[Tree[Int]]
である独自のスタックを使用して、すべてのリーフの合計を計算します。しかし、このケースでは、オペレータの左手側と右手側のどちらを最初に評価するかは重要ではないので、追加する場合にのみ機能します。しかし一般化された倍の場合、それはかなり関連性があります。ここに私の意思を表示するには、いくつかの例の木は、以下のとおりです。
val oldNewPairs =
trees.map(t => (t, fold(t)(Leaf(_): Tree[Int])(Branch(_, _))))
そして平等の条件その証拠:私のような特定のフォールド方法でディープコピーを作成したいものを木に基づいて
val leafs = Branch(Leaf(1), Leaf(2))
val left = Branch(Branch(Leaf(1), Leaf(2)), Leaf(3))
val right = Branch(Leaf(1), Branch(Leaf(2), Leaf(3)))
val bal = Branch(Branch(Leaf(1), Leaf(2)), Branch(Leaf(3), Leaf(4)))
val cmb = Branch(right, Branch(bal, Branch(leafs, left)))
val trees = List(leafs, left, right, bal, cmb)
作成されたすべてのコピーに適用されます:
val conditionHolds = oldNewPairs.forall(p => {
if (p._1 == p._2) true
else {
println(s"Original:\n${p._1}\nNew:\n${p._2}")
false
}
})
println("Condition holds: " + conditionHolds)
誰かが私にいくつかのポインタを教えてください。
あなたはScalaFiddleでこの質問に使用されるコードを見つけることができます:https://scalafiddle.io/sf/eSKJyp2/15
プログラムはScalaFiddleの例のために終了しません。また、 'leafs'のためにこれをAmmoniteで実行しようとすると' java.lang.OutOfMemoryError:Java heap space'エラーが発生します。 – adamwy
@adamwyあなたが正しいです、スタックが消費されていない「支店」のケースでタイプミスがありました。私は答えを編集しました –
ScalaFiddleでこれを取得しました:オリジナル:ブランチ(リーフ(1)、ブランチ(リーフ(2)、リーフ(3) 2))、Leaf(3)) 条件が成り立ちます:false' – adamwy