Рубиновый амперсанд

Возможный дубликат:
Что означает map (&: name) в Ruby?

В Ruby я знаю, что если я это сделаю:

some_objects.each(&:foo)

Это то же самое, что и

some_objects.each { |obj| obj.foo }

То есть &:foo создает блок { |obj| obj.foo }, превращает его в Proc и передает его каждому. Почему это работает? Это просто особый случай Ruby, или есть причина, почему это работает так, как есть?

Ответ 1

Ваш вопрос не так, если можно так выразиться. Здесь происходит не "амперсанд и двоеточие", это "амперсанд и объект". Двоеточие в этом случае для символа. Итак, там & и там :foo.

& вызывает to_proc объекта и передает его как блок для метода. В Rails to_proc реализуется на Symbol, так что эти два вызова эквивалентны:

something {|i| i.foo }
something(&:foo)

Кроме того, to_proc на Symbol реализован в Ruby 1.8.7 и 1.9, поэтому на самом деле это "рубиновая вещь".

Итак, подведем итог: & вызывает to_proc объекта и передает его как блок методу, а Ruby реализует to_proc на Symbol.

Ответ 2

Нет ничего особенного в комбинации амперсанда и символа. Здесь пример того, что (ab) использует регулярное выражение:

class Regexp
  def to_proc
    ->(str) { self =~ str ; $1 }
  end
end
%w(station nation information).map &/(.*)ion/

=> ["stat", "nat", "informat"]

Или целые числа.

class Integer
  def to_proc
    ->(arr) { arr[self] }
  end
end

arr = [[*3..7],[*14..27],[*?a..?z]]
arr.map &4
=> [7, 18, "e"]

Кому нужно arr.map(&:fifth), если у вас есть arr.map &4?