Yorkshireman
Yorkshireman

Reputation: 2343

Ruby returning from inside a method but outside a loop

Try running this code.

When method1 is run, the hash is returned twice, meaning the hash is returned and printed as intended by the 'puts method1().inspect' command.

When method2 is run, and the loop is exited second time-around, by typing "no" or "n", a bunch of seemingly random numbers are printed, instead of a lovely hash. Why is this????

def method1

    loop do
        print "Item name: "
        item_name = gets.chomp

        print "How much? "
        quantity = gets.chomp.to_i

        hash = {"Item"=> item_name, "quantity"=> quantity}
        puts hash.inspect

        return hash
    end

end

puts method1().inspect


def method2

    loop do
        print "Item name: "
        item_name = gets.chomp

        print "How much? "
        quantity = gets.chomp.to_i

        hash = {"Item"=> item_name, "quantity"=> quantity}
        puts hash.inspect

        print "Add another item? "
        answer = gets.chomp.downcase
        break if (answer == "no") || (answer == "n")
    end

    return hash

end

puts method2().inspect

Upvotes: 0

Views: 655

Answers (2)

Jaime Bellmyer
Jaime Bellmyer

Reputation: 23307

In method2, you're trying to return something (hash) that has gone out of scope.

In method1, you're still inside the loop where hash was defined when you return it. In method2, you're outside of the scope where hash was defined, so it has an undocumented outcome. Redefined method2 like so:

def method2
    hash = nil

    loop do
        print "Item name: "
        item_name = gets.chomp

        print "How much? "
        quantity = gets.chomp.to_i

        hash = {"Item"=> item_name, "quantity"=> quantity}
        puts hash.inspect

        print "Add another item? "
        answer = gets.chomp.downcase
        break if (answer == "no") || (answer == "n")
    end

    return hash

end

Now, even though hash was initially set to nil, its scope includes the entire method, and the value will be retained.

Upvotes: 0

Nick Veys
Nick Veys

Reputation: 23939

You've accidentally discovered the Object#hash method. You don't declare hash outside the loop, so it is not in scope to return at the end. Instead, it returns the hash() method value, which is a big negative number for that instance.

Fire up irb, and just type hash, you'll see the same thing:

(505)⚡️ irb
2.1.2 :001 > hash
 => -603961634927157790 

So instead, try this:

def method2
    hash = {}
    loop do
        # ...

Also be aware you aren't adding to the hash, you're re-creating it every time.

Upvotes: 2

Related Questions