cardview - ¿Cuál es la diferencia básica entre doblar y reducir en Kotlin? ¿Cuándo usar cuál?
com alespero expandable cardview (2)
Estoy pasando por lo básico de Kotlin y estoy bastante confundido con ambas funciones fold () y reduce () en Kotlin, ¿alguien puede darme un ejemplo concreto que los distinga a ambos?
La principal diferencia funcional que llamaría (que se menciona en los comentarios en la otra respuesta, pero puede ser difícil de entender) es que
reduce
arrojará una excepción
si se realiza en una colección vacía.
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can''t be reduced.
Esto se debe a que
.reduce
no sabe qué valor devolver en caso de que "no haya datos".
Compare esto con
.fold
, que requiere que proporcione un "valor inicial", que será el valor predeterminado en el caso de una colección vacía:
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
Por lo tanto, incluso si no desea agregar su colección a un solo elemento de un tipo diferente (no relacionado) (que solo
.fold
le permitirá hacer), si su colección inicial puede estar vacía, entonces debe verificar el tamaño de su colección primero y luego
.reduce
, o simplemente usar
.fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)
fold
toma un valor inicial, y la primera invocación de la lambda que le pase recibirá ese valor inicial y el primer elemento de la colección como parámetros.
Por ejemplo, tome el siguiente código que calcula la suma de una lista de enteros:
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
La primera llamada a la lambda será con los parámetros
0
y
1
.
Tener la capacidad de pasar un valor inicial es útil si tiene que proporcionar algún tipo de valor o parámetro predeterminado para su operación. Por ejemplo, si estaba buscando el valor máximo dentro de una lista, pero por alguna razón desea devolver al menos 10, puede hacer lo siguiente:
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce
no toma un valor inicial, sino que comienza con el primer elemento de la colección como el acumulador (denominado
sum
en el siguiente ejemplo).
Por ejemplo, hagamos una suma de enteros nuevamente:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
La primera llamada a la lambda aquí será con los parámetros
1
y
2
.
Puede usar
reduce
cuando su operación no depende de ningún valor distinto de los de la colección a la que lo está aplicando.