Що означає `& метод (: функція)`?


15

Що &method(:function)означає? Наприклад, у мене є такий рядок:

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

Два чудових відповіді (поки що). Щасливчик!
Cary Swoveland

Відповіді:


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))

Тепер, замість того, щоб кожне число використовувалося як приймач для 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 , а не an UnboundMethod. Метод прив’язаний до приймача, оскільки ви викликаєте його в екземплярі, і таким чином він знає, що selfтаке, тоді як Module#instance_methodповертає, UnboundMethodоскільки він не може знати, з яким екземпляром він буде використовуватися.
Йорг W Міттаг

@ JörgWMittag Добре спасибі за виправлення, ви праві, я, мабуть, змішував це, .instance_methodтому що я щойно проходив (помилково) пам’яті
макс-чиститель

10

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

:functionє Symbolбуквальним, тобто це буквальне позначення a Symbol. Symbolце тип даних, що представляє "ім'я чогось".

&Одинарний префікс ampersand оператор "розкручує" a Procв блок . Тобто це дозволяє пройти Procтуди, де очікується блок . Якщо об'єкт ще не a Proc, йому буде надіслано to_procповідомлення, що дозволяє йому перетворити себе в a 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

Але виражається в тому, що зазвичай називають точковим стилем .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.