3

As we know, wo can pass a method to a iterator method by a &: prefix.
For example:

["a", "b"].map(&:upcase) #=> ["A", "B"] 
def rettwo
  2
end
["a", "b"].map(&:rettwo) #=> [2, 2]

Here is the problem, when I write a method, pass a method with &: prefix to it, I got a error message: "ArgumentError: no receiver given".
Let me show the code:

def a_simple_method &proc
  puts proc.class # it shows `Proc`
  proc.call
end
def a_iterator_method
  puts yield
end

a_simple_method &:rettwo #=> ArgumentError: no receiver given
a_iterator_method &:rettwo #=> ArgumentError: no receiver given

What do I missing, How the map like method of Array handle it

Liao Pengyu
  • 591
  • 3
  • 12

1 Answers1

4

Here's what works. Explanation below.

class String
  def rettwo
    self + self
  end
end

def a_simple_method &proc
  proc.call('a')
end

def a_iterator_method
  yield 'b'
end

a_simple_method(&:rettwo) # => "aa"
a_iterator_method(&:rettwo) # => "bb"

The &: construct is called Symbol#to_proc. It turns symbol into a proc. This proc expects a receiver as a first argument. The remaining arguments are used to call the proc. You're not passing any arguments, hence the "receiver not given" error.

Here's a demonstration of additional arguments:

class String
  def say name
    "#{self} #{name}"
  end
end

def a_simple_method &proc
  proc.call('hello', 'ruby')
end


a_simple_method(&:say) # => "hello ruby"

Here's a definition of Symbol#to_proc from some blog post from 2008. Modern Symbol#to_proc seems to be implemented in C, but this can still help the understanding.

class Symbol
  def to_proc
    Proc.new { |*args| args.shift.__send__(self, *args) }
  end
end
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • And I get some other message for addition: Every method defined outside any class will become a private method of every class, this explain why `["a", "b"].map(&:rettwo)` works: In interior of map, it do proc.call(element), and `rettwo` really became a private method of its elements – Liao Pengyu Nov 13 '12 at 18:01