user3097405
user3097405

Reputation: 823

How does the memo in #inject work?

I'm trying to use a while loop inside #inject. However, the last memo becomes nil at some point and I don't understand why. Here is my example (I use #each on the example just to show the expected result):

class TestClass
  BASE_ARRAY = [5, 1]

  def test_method(value)
    result = []

    BASE_ARRAY.each do |item|
      while item <= value
        result << item
        value -= item
      end
    end

    result
  end

  def test_method_alternate(value)
    BASE_ARRAY.inject do |memo, item|
      while item <= value
        p memo
        # memo << item (if left, returns NoMethodError for nil Class)
        value -= item
      end
    end
  end
end

solution_one = TestClass.new.test_method(11)
p solution_one # => [5, 5, 1]

solution_two = TestClass.new.test_method_alternate(11)
p solution_two 
# => [] 
     [] 
     nil  

How does the accumulator become nil?

Upvotes: 0

Views: 225

Answers (2)

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123553

You're getting nil initially from the while loop:

The result of a while loop is nil unless break is used to supply a value.

That result becomes the result of other statements in a chain:

while
-> do |memo, item|
  -> BASE_ARRAY.inject
    -> test_method_alternate(11)
      -> solution_two

To have .inject fill up an array, you'll want to provide an empty array to use as the first memo:

BASE_ARRAY.inject([]) do |memo, item|
# ...            ^^^^

Then, be sure the array is the result of the block:

... do |memo, item|
  while item <= value
    memo << item
    value -= item
  end
  memo # <---
end

Upvotes: 1

Paul Fioravanti
Paul Fioravanti

Reputation: 16793

Two things:

  • You need to initialize the memo with a value, in this case, you'll want a [].
  • You need to return the memo on each iteration of inject.

So, you should get your desired result of [5, 5, 1] by changing your method to be like this:

def test_method_alternate(value)
  BASE_ARRAY.inject([]) do |memo, item|
    while item <= value
      memo << item
      value -= item
    end
    memo
  end
end

Upvotes: 1

Related Questions