Я видел это несколько раз, но я не могу понять, как их использовать. Пикап говорит, что это специальные ярлыки, но я не смог найти синтаксическое описание.
Я видел их в таких контекстах:
[1,2,3].inject(:+)
для вычисления суммы, например.
Я видел это несколько раз, но я не могу понять, как их использовать. Пикап говорит, что это специальные ярлыки, но я не смог найти синтаксическое описание.
Я видел их в таких контекстах:
[1,2,3].inject(:+)
для вычисления суммы, например.
Начнем с более простого примера. Скажем, у нас есть массив строк, которые мы хотим иметь в шапках:
['foo', 'bar', 'blah'].map { |e| e.upcase }
# => ['FOO', 'BAR', 'BLAH']
Кроме того, вы можете создать так называемые объекты Proc (закрытие):
block = proc { |e| e.upcase }
block.call("foo") # => "FOO"
Вы можете передать такой процесс методу с синтаксисом:
block = proc { |e| e.upcase }
['foo', 'bar', 'blah'].map(&block)
# => ['FOO', 'BAR', 'BLAH']
Что это значит, это вызов to_proc на блоке, а затем вызывает это для каждого блока:
some_object = Object.new
def some_object.to_proc
proc { |e| e.upcase }
end
['foo', 'bar', 'blah'].map(&some_object)
# => ['FOO', 'BAR', 'BLAH']
Теперь Rails сначала добавила метод to_proc к Symbol, который позже был добавлен в библиотеку ядра ruby:
:whatever.to_proc # => proc { |e| e.whatever }
Поэтому вы можете сделать это:
['foo', 'bar', 'blah'].map(&:upcase)
# => ['FOO', 'BAR', 'BLAH']
Кроме того, символ # to_proc еще более умный, поскольку он на самом деле делает следующее:
:whatever.to_proc # => proc { |obj, *args| obj.send(:whatever, *args) }
Это означает, что
[1, 2, 3].inject(&:+)
равно
[1, 2, 3].inject { |a, b| a + b }
инъекция принимает символ как параметр, этот символ должен быть именем метода или оператора, который является следующим :+
поэтому [1,2,3].inject(:+)
передает каждое значение методу, указанному символом, поэтому суммирует все элементы в массиве.