# Array.inject

January 23, 2011

Having had a lot of fun last week doing Uncle Bob's prime factors kata, I've been doing the Codebreaker example from the RSpec book this week. In section 9.2 the `number_match_count` method is refactored to be

``````def number_match_count
total_match_count - exact_match_count
end``````

And the problem of implementing `total_match_count` is discussed. The book starts with

``````def total_match_count
count = 0
secret = @secret.split('')
@guess.split('').map do |n|
if secret.include?(n)
secret.delete_at(secret.index(n))
count += 1
end
end
count
end``````

I didn't like this so in a separate branch I came up with

``````def total_match_count
total_match_count = 0
secret = @secret.clone # need a copy as we will slice destructively
@guess.each_char do |char|
pos = secret.index(char)
secret.slice!(pos) and total_match_count +=1 if pos
end
total_match_count
end``````

Which is OK, but fairly similar.

What the RSpec book is leading upto though is

``````def total_match_count
secret = @secret.split('')
@guess.split('').inject(0) do |count, n|
count + (delete_first(secret, n) ? 1 : 0)
end
end

def
delete_first(code, n) code.delete_at(code.index(n)) if code.index(n)
end``````

This uses Array.inject, something I have always avoided. This is the second time the book has focused on Array.inject, and I started thinking why the fascination with inject. What is it that Ruby programmers like about it that I'm missing.

Some googling produced

1. Jay Fields loves inject

2. This thread, of which the best bits are:

-

``````How I remember:  Inject takes a binary operation (e.g. +) and injects
it between each element of a list.

[1,2,3].inject { |a,b| a+b }  => 1+2+3

-- Jim Weirich
``````

-

``````... there is a fundamental difference between the inject and each
versions.  The "each" verison is procedural.  It defines state (the
value of b) and how that state changes in each iteration (b += a).

The "inject" version is functional.  There are no extra state
variables in our code that need initialization.  And the expression
itself is the value, rather than having a side effect on a local
variable.

Not that one way is better than the other, just noting differences.

-- Jim Weirich
``````

-

``````    So, in math-speak, I think one could say:

inject applies a block pairwise as an n-ary operation over an
Enumerable, with an optional initial value.

-- A LeDonne
``````

Perhaps Array.inject is worth investigating further as a step towards doing more functional programming.