Что означает `& method (: function)`?

15

Что &method(:function)значит? Например, у меня есть эта строка:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
источник
Два отличных ответа (пока). Повезло тебе!
Кэри Свовеланд

Ответы:

13

Скажем, у нас есть метод

def add_one(num)
  num + 1
end

и массив строк

arr = ["1", "2"]

Мы хотим, чтобы mapсписок строк для их соответствующих выходов из add_one.

Для начала мы можем позвонить

nums = arr.map(&:to_i)

Это то же самое, что

nums = arr.map do |str|
  str.to_i
end

Вы можете увидеть, что означает карта (&: name) в Ruby? для получения дополнительной информации об этом.

Тем не менее, это не будет работать, чтобы позвонить:

nums.map(&:add_one)

Почему? Потому что числа не имеют встроенного метода add_one. Таким образом, вы получите NoMethodError.

Таким образом, вместо предоставления только имени метода :add_one вы можете передать связанный метод method(:add_one) :

nums.map(&method(:add_one))

Теперь вместо каждого num, используемого в качестве получателя для add_oneметода, они будут использоваться в качестве аргументов . Итак, по сути это то же самое, что и:

nums.map do |num|
  add_one(num)
end

Чтобы привести другой пример, сравните следующее:

[1].map(&:puts)
# this is the same as [1].map { |num| num.puts }
# it raises NoMethodError

[1].map(&method(:puts))
# this is the same as [1].map { |num| puts num }
# it prints 1 successfully
Макс Плинер
источник
Nitpick: Object#methodвозвращает ограничение Method , а не UnboundMethod. Метод привязан к получателю, потому что вы вызываете его для экземпляра, и он, таким образом, знает, что selfесть, а Module#instance_methodвозвращает, UnboundMethodпотому что не может знать, с каким экземпляром он будет использоваться.
Йорг Миттаг
@ JörgWMittag Хорошо, спасибо за исправление, вы правы, я, должно быть, смешивал это, .instance_methodпотому что у меня просто (испорченная) память
макс плеанер
10

method(:function)является отправкой сообщения (иногда называемого вызовом метода ) неявному получателю (то есть self). Он отправляет сообщение methodнеявному получателю (то есть self), передавая :functionв качестве единственного аргумента.

:functionявляется Symbolбуквальным, то есть это буквальное обозначение Symbol. Symbolтип данных, представляющий «имя чего-либо».

Оператор амперсанда с одинарным префиксом &«разворачивает» Procв блок . Т.е. он позволяет вам пройти там, Procгде ожидается блок . Если объект еще не является a Proc, ему будет отправлено to_procсообщение, позволяющее ему преобразовать себя в Proc. (Оператор допустим только в списке аргументов и только для последнего аргумента. Это двойственный &символ в списке параметров, который «сворачивает» блок в Procобъект.)

Procтип данных, представляющий исполняемый код Это основной библиотечный класс Ruby для первоклассных подпрограмм.

Итак, для этого нужно вызвать methodметод selfс :functionаргументом, вызвать to_procвозвращаемое значение, «развернуть» полученный Procобъект в блок и передать этот блок в вызов, integrateкак если бы вы написали что-то вроде

res = integrate(0, 1, a) do
  # something
end

methodМетод здесь, скорее всего, Object#methodметод, который возвращает связанный Method объект.

Итак, в целом, это несколько эквивалентно

res = integrate(0, 1, a) do |*args, &block|
  function(*args, &block)
end

Но выражается в том, что принято называть точечным стилем .

Йорг Миттаг
источник