scala - una - reglas para dar vuelta a la izquierda
Diferencia entre doblar y doblar hacia la izquierda o doblar hacia la derecha? (5)
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)(_ + _)
^
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
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)
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 suman no está definido. Es decir, los argumentos para formar un monoid .
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.
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.