Когда вы говорите :method
, вы используете хороший синтаксический сахар в рубине, который создает новый объект Symbol. Когда вы бросаете амперсанд перед ним (&:method
), вы используете другой кусок сахара. Это вызывает метод to_proc
на символе.
Таким образом, эти две вещей идентичны:
method_proc = &:method
sym = :method
method_proc = method.to_proc
Какая разница между этим и другим использованием? Ну, у respond_to?
есть один аргумент - символ. Таким образом, мы можем пройти :method
, и все будет хорошо и денди. (Интересно, что объекты отвечают методу method
, но это гораздо более запутанный вопрос).
Для сравнения, итераторы Enumerable (например, map
, select
и т. Д.) Принимают блок. Когда мы передаем Proc, он правильно интерпретируется как этот блок. Таким образом, эти два фрагмента кода эквивалентны:
[1,2,3].map { |i| i.even? }
[1,2,3].map(&:even?)
Эта эквивалентность немного сбивает с толку, потому что, конечно, символ не имеет представления о том, что есть even?
метод где-то. Чтобы поиграть с ним, я использовал evenproc = :even?.to_proc
для проверки полученного результата. Он реализован в C (по крайней мере, в рубине MRI) и не хочет отказываться от своего источника. Однако его arity - это -1
, что означает, что он принимает один необязательный аргумент arg. Мое предположение, что он делает что-то вроде этого:
def to_proc
method_name = self.to_s
->(a) { a.send(method_name) }
end
я мог выкопать дальше, но я думаю, что мы уже прошли мимо этого вопроса. ;) Удачи!