Diferencia entre doblar y doblar hacia la izquierda o doblar hacia la derecha?

NOTA: estoy en Scala 2.8: ¿puede ser un problema?

¿Por qué no puedo usar la función de fold la misma manera que foldLeft o foldRight ?

En el conjunto scaladoc dice que:

El resultado del plegado puede ser solo un supertipo del parámetro de tipo T de esta colección paralela.

Pero no veo ningún parámetro de tipo T en la firma de la función:

 def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1 

¿Cuál es la diferencia entre foldLeft-Right y fold , y cómo uso este último?

EDITAR: por ejemplo, ¿cómo escribiría un doblez para agregar todos los elementos en una lista? Con foldLeft sería:

 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)(_ + _) ^ 

Tiene razón acerca de que la versión anterior de Scala es un problema. Si miras la página scaladoc para Scala 2.8.1, verás que no hay pliegue definido allí (lo cual es consistente con tu mensaje de error). Aparentemente, fold fue introducido en Scala 2.9.

Respuesta corta:

foldRight asocia a la derecha. Es decir, los elementos se acumularán en orden de derecha a izquierda:

 List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z))) 

foldLeft asocia a la izquierda. Es decir, se inicializará un acumulador y los elementos se agregarán al acumulador en orden de izquierda a derecha:

 List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c) 

fold es asociativo porque el orden en el que los elementos se sumn no está definido. Es decir, los argumentos para formar un monoide .

fold , a diferencia de foldRight y foldLeft , no ofrece ninguna garantía sobre el orden en que se procesarán los elementos de la colección. Probablemente desee utilizar fold , con su firma más restringida, con colecciones paralelas, donde la falta de orden de procesamiento garantizado ayuda a la colección paralela a implementar el plegado de forma paralela. La razón para cambiar la firma es similar: con las restricciones adicionales, es más fácil hacer un doblez paralelo.

Para su ejemplo particular, lo codificaría de la misma manera que lo haría con foldLeft.

 val ns = List(1, 2, 3, 4) val s0 = ns.foldLeft (0) (_+_) //10 val s1 = ns.fold (0) (_+_) //10 assert(s0 == s1) 

De acuerdo con otras respuestas pensado en dar un simple ejemplo ilustrativo:

  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) } } 

El resultado es auto explicativo:

 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 
    Intereting Posts