Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: methods as array elements - how do they work?

Tags:

ruby

This probably isn't something you should try at home, but for some reason or another I tried to create an array of methods in Ruby.

I started by defining two methods.

irb(main):001:0> def test1
irb(main):002:1>   puts "test!"
irb(main):003:1> end
=> nil
irb(main):004:0> def test2
irb(main):005:1>   puts "test2!"
irb(main):006:1> end
=> nil

The weird thing happens when you try to put it into an actual array. It seems to run both methods.

irb(main):007:0> array = [test1, test2]
test!
test2!
=> [nil, nil]

And afterwards, the array is empty.

irb(main):008:0> puts array


=> nil

Can someone explain to me why it runs the methods? Other than that the whole excercise is seriously in need of an exorcist?

like image 555
Nekkoru Avatar asked Dec 19 '12 09:12

Nekkoru


4 Answers

What you're storing in your array is the result of calling your methods, not the methods themselves.

def test1
  puts "foo!"
end

def test2
  puts "bar!"
end

You can store references to the actual methods like this:

> arr = [method(:test1), method(:test2)]
# => [#<Method: Object#test1>, #<Method: Object#test2>] 

Later, you can call the referenced methods like this:

> arr.each {|m| m.call }
foo!
bar!
like image 122
Lars Haugseth Avatar answered Sep 30 '22 17:09

Lars Haugseth


@alestanis explained the reason well. If you were trying to store the methods, then you can do what Lars Haugseth says or you could do the folllowing:

test1 = Proc.new { puts "test!" }
test2 = Proc.new { puts "test2!" }
a = [test1, test2]

This may make your code much more readable.

Here is an irb run.

1.9.3p194 :009 > test1 = Proc.new { puts "test!" }
 => #<Proc:0x00000002798a90@(irb):9> 
1.9.3p194 :010 > test2 = Proc.new { puts "test2!" }
 => #<Proc:0x00000002792988@(irb):10> 
1.9.3p194 :011 > a = [test1, test2]
 => [#<Proc:0x00000002798a90@(irb):9>, #<Proc:0x00000002792988@(irb):10>] 
like image 39
Martin Velez Avatar answered Sep 30 '22 18:09

Martin Velez


Your array never contains anything else than two nil values. I tricks you by putting the strings when evaluating. But the return value of each function still is nil.

like image 39
iltempo Avatar answered Sep 30 '22 18:09

iltempo


Your code runs the two methods because you're actually calling the methods when you say "test1" and "test2" - parentheses are optional for ruby method calls.

Since both of your methods just contain a "puts", which returns nil, your resulting array is just an array of two nils.

like image 40
tom Avatar answered Sep 30 '22 16:09

tom