Iteratoren: inject und reduce

In Ruby gibt es verschiedene Formen zu iterieren (Schleifendurchläufe). Vermutlich am häufigsten wird dafür auf Enumerator#each zurückgegriffen. Und das, obwohl es für bestimmte Fälle eine dedizierte Alternative gibt. Akkumulation ist so eine spezielle Form der Iteration.
Mit each sieht eine Akkumulation so aus:

sum = 0
(1..10).each { |number| sum += number }  # => 1..10
sum # => 55

Das ist aus folgenden Gründen ungünstig: 1. Die Ergebnisvariable muss explizit initialisiert werden 2. Enumerator#each sagt wenig über das aus, was in der Iteration passiert 3. Der Rückgabewert der Iteration ist nicht das Ergebnis der Iteration

Ruby bietet für Akkumulationen Enumerable#inject und Enumerable#reduce, wobei inject der Alias von reduce ist. Grundsätzlich sollte der Alias nur verwendet werden, wenn es die Lesbarkeit erhöht.
Das selbe Akkumulationsbeispiel mit reduce:

(1..10).reduce(0) { |sum, number| sum += number }  # => 55

Es wurden zwar 3 Zeilen auf 1 Zeile eingedampft, der eigentlich Mehrwert liegt aber in der erhöhten Lesbarkeit. Jeder, der die Zeile liest, weiß schon anhand des Iterators, dass hier ein Akkumulationsergebnis zurückgegeben wird. In diesem Fall ist es eine Summe.
Es könnten aber auch ein paar HTML Tags sein, die von einer Ruby on Rails helper Methode generiert werden:

def names names
  names.inject(''.html_safe) { |name, html| html << content_tag(:span, name) }
end

Das Ganze läßt sich aber sogar noch kompakter ausdrücken. Das Ruby Summationsbeispiel noch einmal:

(1..10).reduce(:+) # => 55