takeUniqBy

Los primeros count elementos cuya clave es nueva, como lista — una clave null se salta el elemento, así que un solo callback selecciona y da la clave.

List<A> takeUniqBy<A, B extends Object>(int count, B? Function(A a) f, Iterable<A> iterable) List<T> Fx<T>.takeUniqBy<B extends Object>(int count, B? Function(T a) f) // chain // Strict: returns a List, runs when called. A null key skips the element, // so f both selects and keys — filter + uniqBy + take in one call.

Lección

takeUniqBy(3, key, xs) es filter + uniqBy + take escrito como una única llamada estricta. Devuelve una List, se ejecuta cuando la llamas y se detiene en cuanto alcanza la cuenta: los elementos posteriores nunca se inspeccionan. La única vuelta de tuerca es el callback: devuelve una clave, y devolver null significa «salta este elemento». Esa es la forma filter_map, y es lo que permite que una sola función haga el trabajo de dos.

Escribe la cadena por defecto. Tres pasos con nombre se leen mejor que un callback respondiendo a dos preguntas, y la cadena perezosa corta igual de bien. Este operador existe por un solo motivo, y conviene saber cuál es.

Por qué existe: el callback que el compilador no puede ver

Una etapa perezosa guarda su callback en un campo del iterador. El compilador AOT no puede ver a través de un campo, así que el closure nunca se inserta: cada elemento paga una llamada indirecta real y su cuerpo jamás se funde con el bucle que lo rodea. Dos etapas, dos llamadas por elemento. Eso es la mayor parte de lo que separa una cadena idiomática de FxDart de un bucle escrito a mano.

takeUniqBy recibe su callback como parámetro de un cuerpo lo bastante pequeño para insertarse en el punto de llamada, así que el compilador inserta con él el cuerpo del closure. Medido sobre 1.000.000 de líneas de log, AOT:

FormaTiempo
filter().uniqBy().take(3)13,7 ms
takeUniqBy(3, …)11,3 ms
un bucle escrito a mano10,2 ms

Ambas formas, y ambas barras, están en Mensajes de error recientes, deduplicados: la página de comparación que publica tres barras en lugar de dos, porque la diferencia entre dos maneras de escribir la misma tubería es precisamente lo que quiere mostrar.

Así que: recurre a esto cuando la tubería esté en el camino caliente y un perfilador diga que estos callbacks son el coste. Antes no. Extensión de fxdart — sin equivalente en FxTS, y sin gemelo asíncrono: la ganancia es la inserción, que la maquinaria asíncrona eclipsa.

Demo 1 · Los tres errores distintos más recientes

Demo 2 · null salta, count es un techo

Pruébalo tú

Ejercicio: los primeros tres usuarios distintos que llegaron a una página.

Relacionado: uniqBy — la deduplicación perezosa que absorbe · take — el truncado perezoso que absorbe · uniqStrict — el otro miembro estricto de la familia · Rendimiento — de dónde sale el suelo de los callbacks