Что означает `& method (: function)`? - PullRequest
15 голосов
/ 11 января 2020

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

res = integrate(0, 1, a, &method(:function))

Ответы [ 2 ]

13 голосов
/ 11 января 2020

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

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

Вы можете увидеть Что означает map (&: 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
10 голосов
/ 11 января 2020

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

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

Унарный префикс ampersand &, оператор «разворачивает» Proc в блок . Т.е. он позволяет передать Proc, где ожидается блок . Если объект не является 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, который возвращает bound Method object.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...