Ответ Джоша Ли является почти правильным, за исключением того, что эквивалентный код Ruby должен был выглядеть следующим образом.
class Symbol
def to_proc
Proc.new do |receiver|
receiver.send self
end
end
end
не
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
С этим кодом, когда выполняется print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
, Ruby разбивает первый вход [1,'a']
на 1 и 'a', чтобы дать obj
1 и args*
'a', чтобы вызвать ошибку, как это делает объект Fixnum 1 не иметь метод self (который: first).
Когда выполняется [[1,'a'],[2,'b'],[3,'c']].map(&:first)
;
:first
является объектом Symbol, поэтому, когда &:first
передается методу карты в качестве параметра, вызывается Symbol # to_proc.
map отправляет сообщение о вызове: first.to_proc с параметром [1,'a']
, например, :first.to_proc.call([1,'a'])
выполняется.
Процедура to_proc в классе Symbol отправляет сообщение об отправке объекту массива ([1,'a']
) с параметром (: first), например, [1,'a'].send(:first)
выполняется.
перебирает остальные элементы в [[1,'a'],[2,'b'],[3,'c']]
объекте.
Это то же самое, что и выражение [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
.