注:Scala 2.8—それが問題になりますか?
fold
またはfoldLeft
と同じ方法でfoldRight
関数を使用できないのはなぜですか?
Set scaladoc には次のように書かれています:
折りたたみの結果は、この並列コレクションの型パラメーター
T
のスーパータイプのみになります。
しかし、関数シグネチャに型パラメーターT
はありません。
def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1
foldLeft-Right
とfold
の違いは何ですか。後者をどのように使用しますか?
編集:たとえば、リスト内のすべての要素を追加するために折り畳みをどのように作成しますか? foldLeft
の場合:
val foo = List(1, 2, 3)
foo.foldLeft(0)(_ + _)
// now try fold:
foo.fold(0)(_ + _)
>:7: error: value fold is not a member of List[Int]
foo.fold(0)(_ + _)
^
古いバージョンのScala=が問題です。 scaladocページ for Scala= 2.8。 1、そこに定義された折り畳みは表示されません(これはエラーメッセージと一致します)明らかに、fold
はScala 2.9。
短い答え:
foldRight
は右側に関連付けられます。つまり要素は右から左の順に蓄積されます。
List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))
foldLeft
は左に関連付けられます。つまりアキュムレータが初期化され、要素が左から右の順にアキュムレータに追加されます。
List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c)
fold
はassociativeです。要素が一緒に追加される順序は定義されていません。つまりfold
の引数は、モノイドを形成します。
fold
は、foldRight
およびfoldLeft
とは異なり、コレクションの要素が処理される順序に関する保証を提供しません。おそらく、処理が保証されていない並列コレクションで、より制約の多いシグネチャを持つfold
を使用することをお勧めします。処理順序が保証されていないため、並列コレクションは並列にフォールディングを実装できます。署名を変更する理由は似ています。制約が追加されているため、平行折りを行うのが簡単です。
他の答えに同意します。簡単な説明例を与えると考えました:
object MyClass {
def main(args: Array[String]) {
val numbers = List(5, 4, 8, 6, 2)
val a = numbers.fold(0) { (z, i) =>
{
println("fold val1 " + z +" val2 " + i)
z + i
}
}
println(a)
val b = numbers.foldLeft(0) { (z, i) =>
println("foldleft val1 " + z +" val2 " + i)
z + i
}
println(b)
val c = numbers.foldRight(0) { (z, i) =>
println("fold right val1 " + z +" val2 " + i)
z + i
}
println(c)
}
}
fold val1 0 val2 5
fold val1 5 val2 4
fold val1 9 val2 8
fold val1 17 val2 6
fold val1 23 val2 2
25
foldleft val1 0 val2 5
foldleft val1 5 val2 4
foldleft val1 9 val2 8
foldleft val1 17 val2 6
foldleft val1 23 val2 2
25
fold right val1 2 val2 0
fold right val1 6 val2 2
fold right val1 8 val2 8
fold right val1 4 val2 16
fold right val1 5 val2 20
25
特定の例では、foldLeftと同じ方法でコーディングします。
val ns = List(1, 2, 3, 4)
val s0 = ns.foldLeft (0) (_+_) //10
val s1 = ns.fold (0) (_+_) //10
assert(s0 == s1)