mko
mko

Reputation: 22064

how does Array#map have parameter to do something like this?

def double(a)
 a*2
end

method_object = method(:double)

and here's my question, how does this code:

[1,3,5,6].map(&method_object)

achieve the same result of

[1,3,5,6].map {|x| method_object.call(x)}

in the Ruby document, the Array#map only can have block, not normal parameter

ary.collect {|item| block } → new_ary ary.map {|item| block } → new_ary ary.collect → an_enumerator ary.map → an_enumerator

Upvotes: 2

Views: 223

Answers (2)

antonversal
antonversal

Reputation: 1239

you can extend class integer:

class Integer
  def double
    self*2
  end
end

[1,2,3,4].map(&:double)
[
    [0] 2,
    [1] 4,
    [2] 6,
    [3] 8
]

Upvotes: 0

Miki
Miki

Reputation: 7188

Simply put, the ampersand & is used to "pack / unpack" a method object to a block, so the effect is more-less the same as if you passed the block.

You can "get" the block that has been passed to your method by:

def method_with_block(&foo)
  # do something here
  foo.call
  # do something else
end

This will be similar to calling yield and not declaring &foo as parameter. I think binding might differ between the two approaches, but in most cases the effect is what you would expect (if I am mistaken, please correct).

Of course, the ampersand works the other way around - if a method expects a block and you have a proc object, you can simply prepend it with &, just as you wrote. To be more precise, & calls to_proc method of the passed object (Rails uses this in a manner similar to described in this entry about to_proc.

I hope that this answers some of your doubts. In case there is a mistake in what I wrote, feel free to correct it.

Readings you might find useful:

Upvotes: 3

Related Questions