Estado mutable y bucles. Casi nunca los necesita, y casi siempre obtiene un mejor código sin ellos.
Por ejemplo, esto se toma directamente de un hilo de StackOverflow:
// ECMAScript
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
# Ruby
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
Ambos están haciendo lo mismo. Pero no tengo idea de lo que están haciendo. Afortunadamente, la pregunta realmente explica lo que están haciendo, así que pude reescribirlos de la siguiente manera:
// ECMAScript
things.reduce(function (acc, thing) {
(acc[thing.type] || (acc[thing.type] = [])).push(thing);
return acc;
}, {});
# Ruby
things.group_by(&:type)
// Scala
things groupBy(_.type)
// C#
from thing in things group thing by thing.Type // or
things.GroupBy(thing => thing.Type);
No hay bucles ni estado mutable. Bueno, está bien, no hay bucles explícitos ni contadores de bucles.
El código se ha vuelto mucho más corto, mucho más simple, mucho más parecido a una descripción de lo que se supone que debe hacer el código (especialmente en el caso de Ruby dice casi directamente "agrupe las cosas por tipo"), y mucho menos propenso a errores. No hay peligro de que se salga del final de la matriz, los errores de poste de cerca o los errores de uno por uno con los índices de bucle y las condiciones de terminación, porque no hay índices de bucle ni condiciones de terminación.