Ruby #each .vs. #inject in the Presence of Side-Effects

Note the difference between:

numbers.inject(0) {| sum, x | sum + x }

.vs.

sum = 0
numbers.each {| x | sum += x }
sum

… the former is obviously preferred.

However:

If the #inject result value is mutated *and* the result value is used elsewhere (or implicitly returned), use a local variable with #each, instead of #inject.

Rationale:

  • Initial assignment to result and #each implies side-effects.
  • Block’s return value does not matter, therefore cannot be broken.
  • #each is easier to understand.
  • #each is (usually) faster than #inject.
1
2
3
4
5
result = { }
sequence.each do | x |
  result[foo(x)] = bar(x)
end
result

instead of:

1
2
3
4
sequence.inject({}) do | result, x |
  result[foo(x)] = bar(x)
  result
end

And certainly use a local variable with #each where the result is used often:

1
2
3
4
5
6
result = sequence.inject(side_effected_thing) do | acc, x |
  acc.do_something!(x)
  acc
end
result.foo(y)
bar(result)

Should be:

1
2
3
4
5
6
result = side_effected_thing
sequence.each do | x |
  result.do_something!(x)
end
result.foo(y)
bar(result)

Leave a Reply

Your email address will not be published. Required fields are marked *

*