rubyfunctionloopswhile-looplearn-ruby-the-hard-way

While Loops in Ruby and Converting to a Function


I'm on Chapter 33 of Learn Ruby the Hard Way.

Extra credit exercise 1 asks:

Convert this while loop to a function that you can call, and replace 6 in the test (i < 6) with a variable.

The code:

i = 0
numbers = []

while i < 6
  puts "At the top i is #{i}"
  numbers.push(i)

  i = i + 1
  puts "Numbers now: #{numbers}"
  puts "At the bottom i is #{i}"
end

puts "The numbers: "

for num in numbers
  puts num
end

My attempt:

i = 0
numbers = []

def loops
while i < 6
  puts "At the top i is #{i}"
  numbers.push(i)

  i = i + 1
  puts "Numbers now: #{numbers}"
  puts "At the bottom i is #{i}"
end
 end

 loops
 puts "The numbers: "

for num in numbers
  puts num
end

As you can see, I got as far as trying to make the block into a function, not yet making the 6 a variable.

Error:

ex33.rb:5:in `loops': undefined local variable or method `i' for main:Object (Na
meError)
        from ex33.rb:15:in `<main>'
    from ex33.rb:15:in `<main>'

What am I doing wrong?

EDIT: Okay, improved it a little. Now the numbers variable is out of scope...

def loops (i, second_number)
numbers = []
while i < second_number
  puts "At the top i is #{i}"
    i = i + 1
  numbers.push(i)
  puts "Numbers now: #{numbers}"
  puts "At the bottom i is #{i}"
end
 end

loops(0,6)
puts "The numbers: "

for num in numbers
  puts num
end

Solution

  • As @steenslag says, i is out of scope within loops. I would not recommend switching to using @i because i is only used by loops.

    Your function is a utility that can be used to produce an array of numbers. The function uses i to figure out how far through it is (but the caller of the function doesn't care about this, it only wants the resulting numbers). The function also needs to return numbers, so move that inside loops too.

    def loops
      i = 0
      numbers = []
    
      while i < 6
        puts "At the top i is #{i}"
        numbers.push(i)
    
        i = i + 1
        puts "Numbers now: #{numbers}"
        puts "At the bottom i is #{i}"
      end
    end
    

    You now have to think about the fact that the caller of loops can no longer see numbers. Good luck with your learning.