He aprendido la diferencia básica entre foldLeft
yreduceLeft
foldLeft:
- se debe pasar el valor inicial
reducir Izquierda:
- toma el primer elemento de la colección como valor inicial
- lanza una excepción si la colección está vacía
¿Hay alguna otra diferencia?
¿Alguna razón específica para tener dos métodos con una funcionalidad similar?
scala
functional-programming
fold
higher-order-functions
Rajesh Pitty
fuente
fuente
Respuestas:
Pocas cosas para mencionar aquí, antes de dar la respuesta real:
left
, se trata más bien de la diferencia entre reducir y plegarDe vuelta a su pregunta:
Aquí está la firma de
foldLeft
(también podría haber sidofoldRight
para el punto que voy a hacer):Y aquí está la firma de
reduceLeft
(de nuevo, la dirección no importa aquí)Estos dos se ven muy similares y por lo tanto causaron la confusión.
reduceLeft
es un caso especial defoldLeft
(que por cierto significa que a veces puedes expresar lo mismo usando cualquiera de ellos).Cuando llame a
reduceLeft
say en unList[Int]
, literalmente reducirá toda la lista de enteros en un solo valor, que será de tipoInt
(o un supertipo deInt
, por lo tanto[B >: A]
).Cuando llame a
foldLeft
say en unList[Int]
, plegará toda la lista (imagine rodar un trozo de papel) en un solo valor, pero este valor no tiene que estar relacionadoInt
(por lo tanto[B]
).Aquí hay un ejemplo:
Este método toma un
List[Int]
y devuelve unTuple2[List[Int], Int]
o(List[Int], Int)
. Calcula la suma y devuelve una tupla con una lista de enteros y es la suma. Por cierto, la lista se devuelve hacia atrás, porque usamos enfoldLeft
lugar defoldRight
.Mira One Fold para gobernarlos a todos y obtener una explicación más detallada.
fuente
B
es un supertipo deA
? PareceB
que en realidad debería ser un subtipo deA
, no un supertipo. Por ejemplo, suponiendo queBanana <: Fruit <: Food
si tuviéramos una lista deFruit
s, parece que puede contener algunosBanana
s, pero si contuviera algunoFood
, el tipo seríaFood
, ¿correcto? Así pues, en este caso, siB
es un subtipo de élA
y hay una lista que contiene ambosB
s yA
s, la lista debe ser de tipoB
, noA
. ¿Puedes explicar esta discrepancia?List[Banana]
puede reducirse a un soloBanana
o un soloFruit
o un soloFood
. PorqueFruit :> Banana
y 'Comida:> Plátano'.Banana
puede contener unFruit
", lo que no tiene sentido. Su explicación tiene sentido: laf
función que se pasareduce()
puede dar como resultado aFruit
o aFood
, lo que significa queB
la firma debe ser una superclase, no una subclase.reduceLeft
Es solo un método de conveniencia. Es equivalente afuente
reducelft
embargofold
funciona en una lista vacía, mientrasreduce
que no.foldLeft
es más genérico, puede usarlo para producir algo completamente diferente de lo que introdujo originalmente. MientrasreduceLeft
que solo puede producir un resultado final del mismo tipo o supertipo del tipo de colección. Por ejemplo:El
foldLeft
va a aplicar el cierre con el último resultado plegada (por primera vez usando el valor inicial) y el siguiente valor.reduceLeft
por otro lado, primero combinará dos valores de la lista y los aplicará al cierre. A continuación, combinará el resto de los valores con el resultado acumulativo. Ver:Si la lista está vacía,
foldLeft
puede presentar el valor inicial como un resultado legal.reduceLeft
por otro lado, no tiene un valor legal si no puede encontrar al menos un valor en la lista.fuente
La razón básica por la que ambos están en la biblioteca estándar de Scala es probablemente porque ambos están en la biblioteca estándar de Haskell (llamada
foldl
yfoldl1
). SireduceLeft
no fuera así, a menudo se definiría como un método de conveniencia en diferentes proyectos.fuente
Como referencia, se
reduceLeft
producirá un error si se aplica a un contenedor vacío con el siguiente error.Reelaborando el código para usar
Es una opción potencial. Otra es usar la
reduceLeftOption
variante que devuelve un resultado envuelto en Opción.fuente
De los principios de programación funcional en Scala (Martin Odersky):
[a diferencia de
reduceLeft
, lo que arroja una excepción cuando se invoca en una lista vacía.]El curso (ver lección 5.5) proporciona definiciones abstractas de estas funciones, que ilustran sus diferencias, aunque son muy similares en su uso de la coincidencia de patrones y la recursividad.
Tenga en cuenta que
foldLeft
devuelve un valor de tipoU
, que no es necesariamente el mismo tipo queList[T]
, pero reduceLeft devuelve un valor del mismo tipo que la lista).fuente
Para comprender realmente lo que está haciendo con fold / reduce, consulte esto: http://wiki.tcl.tk/17983 muy buena explicación. una vez que obtenga el concepto de doblar, reducir aparecerá junto con la respuesta anterior: list.tail.foldLeft (list.head) (_)
fuente