Рубиновый амперсанд
Возможный дубликат:
Что означает 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
?