0

Quick question, I've run across this select(&:even) syntax a few times, and I understand it for the most part except for one thing:

The & symbol, to me, is what makes the method name, well a method name. I don't understand why a symbol syntax is needed to define even. In a short example:

arr = [1,2,3,4,5]
puts arr.select(&:even?)

correctly selects and prints all the even numbers but,

arr = [1,2,3,4,5]
puts arr.select(&even?)

produces:

Untitled 3.rb:2:in <main>: undefined method even? for main:Object (NoMethodError)

Can anyone help me understand the necessity of using a : symbol?

inthenameofmusik
  • 617
  • 1
  • 4
  • 16
  • 2
    Method names are symbols, so the reference is to the method `:even?`. The operator `&` does two things: it invokes [Symbol#to_proc](http://ruby-doc.org/core-2.2.0/Symbol.html#method-i-to_proc) on the method name to convert it to a proc (instance of [Proc](http://ruby-doc.org/core-2.2.0/Proc.html)) and then calls the proc. If you instead had `arr.select(&proc)`, it would just call the proc. – Cary Swoveland Oct 13 '15 at 21:29
  • I cannot parse your sentence `(The & symbol, to me, is) what makes the method name, well a method name`. – sawa Oct 13 '15 at 21:39
  • Why would you think it would work without `:`? – sawa Oct 13 '15 at 21:40

1 Answers1

2

As explained in "What does map(&:name) mean in Ruby?", the &:whatever syntax converts the :whatever method in a proc and passes it to the caller.

puts arr.select(&:even?)

is equivalent to

puts arr.select { |x| x.even? }

The reason why &:whatever works whereas &whatever does not, is because in the latter case the Ruby virtual machine will actually try to evaluate whatever and pass the result to &, when what you really want is a sort of lazy-evaluation. You want is to pass a method reference/name to &, not execute the method itself.

The error you experience is because the following code

puts arr.select(&even?)

can be read as

  1. execute even?
  2. get the return value and pass it to &
  3. ... but hey... even? is not defined (notice the target is implicit)... crash!
Community
  • 1
  • 1
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364