Отказ от ответственности: Этот пост является чисто образовательным. nums.each {|n| puts n}
действительно единственная разумная вещь, которую можно написать в реальном проекте.
Понимание nums.map(&:to_s)
Существующая краткая форма работает очень просто. &
вызывает to_proc
для символа, а to_proc
для символа определяется следующим образом.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
Так как этот процесс начнет действовать как обычный блок, который передается в карту, *args
в этом случае - это действительно каждый элемент, через который мы итерируем. Мы берем первое из аргументов (поскольку *
превращает аргументы в массив) и отправляем ему self
, self
- фактический символ, такой как :to_s
. Остальные аргументы передаются. Это как сказать nums.map{ |*args| args.shift.__send__(:to_s, *args) }
.
Изменение его для включения nums.each(&:puts)
Мы могли бы легко реализовать to_proc
, чтобы действовать по-другому. Вот быстрый пример.
class Symbol
def to_proc
Proc.new { |*args| __send__(self, *args) }
end
end
(1..10).each(&:print) # => 12345678910
Здесь вместо того, чтобы отправлять имя символа в качестве сообщения элементу, мы просто вызываем символ как метод в текущем контексте и просто передаем итерированный элемент в качестве аргумента ему.
Так что это больше похоже на высказывание (1..10).each{|*args| __send__(:print, *args)}
.
Понимание nums.each(&method(:puts))
Тем не менее, как отметил Нэш, вы можете позвонить nums.each(&method(:puts))
. В результате вы получаете объект, представляющий метод puts
с использованием метода method
в ruby. Тогда &
вызывает .to_proc
для объекта метода, превращая его в proc, который сам начинает играть роль блока, переданного в each
(или map
). Аргументы, передаваемые в этот процесс (каждый элемент, который вы перебираете), затем становятся аргументами этого метода. Ухоженная.
Реализация xargs
Чтобы избежать перезаписи стандартного поведения, мы могли бы гипотетически реализовать нашу собственную функцию xargs, как в сценариях оболочки. (Не делай этого дома, слишком умный - плохо.)
class Symbol
def to_xargs
Proc.new{ |*args| __send__(self, *args) }
end
end
def xargs(sym)
sym.to_xargs
end
(1..10).each(&xargs(:print)) # prints 12345678910