foldByOrSkip
Reduce por clave como foldBy, salvo que una clave null salta el elemento — así un solo callback selecciona y clasifica.
Lección
foldByOrSkip(key, seed, f, xs) es
filter +
foldBy escrito como una única
llamada estricta. Todo lo que foldBy garantiza sigue en pie:
seed inicia cada clave en lugar de arrastrarse entre ellas,
las claves salen en orden de primera aparición y el mapa se consulta una
vez por elemento. La única vuelta de tuerca es la función de clave:
devolver null significa «salta este elemento», la misma forma
filter_map que usa
takeUniqBy.
Escribe filter(...).foldBy(...) por defecto. Dos pasos con
nombre se leen mejor que un callback respondiendo a dos preguntas, y aquí
esas dos preguntas suelen no tener relación: un rango de fechas y una
categoría no son la misma idea. Este operador existe por un solo motivo, y
conviene saber cuál es.
Por qué existe: el predicado que el compilador no puede ver
filter es una etapa perezosa, así que guarda su
predicado en un campo del iterador. El compilador AOT no puede ver a través
de un campo, de modo que ese predicado nunca se inserta: cada elemento paga
una llamada indirecta real y su cuerpo jamás se funde con el bucle que lo
rodea. foldBy no tiene ese problema: es estricto, así que sus
callbacks son parámetros y sí se insertan. Lo que cuesta es el filtro que
va delante.
foldByOrSkip mueve la prueba dentro de la clave, que es un
parámetro. Medido sobre 1.000.000 de transacciones, AOT, conservando un mes
de doce:
| Forma | Tiempo |
|---|---|
filter().foldBy() | 14,5 ms |
foldByOrSkip(…) | 12,6 ms |
| un bucle escrito a mano | 11,3 ms |
Ambas formas, y ambas barras, están en Informe mensual por categoría: una de las dos páginas de comparación que publican tres barras en lugar de dos, porque la diferencia entre dos maneras de escribir la misma tubería es precisamente lo que quieren mostrar.
Demo 1 · El gasto de julio por categoría
Demo 2 · La semilla, el salto y lo que ve el fold
Pruébalo tú
Ejercicio: la lectura más alta por sensor, ignorando las filas defectuosas.
foldBy — la reducción sobre la que se apoya ·
filter — la etapa que absorbe ·
takeUniqBy — la misma idea para filter + uniqBy + take ·
Rendimiento — de dónde sale el suelo de los callbacks