Co oznacza `& method (: function)`?

15

Co &method(:function)znaczy Na przykład mam tę linię:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
źródło
Dwie doskonałe odpowiedzi (jak dotąd). Szczęściarz!
Cary Swoveland

Odpowiedzi:

13

Powiedzmy, że mamy metodę

def add_one(num)
  num + 1
end

i tablica ciągów

arr = ["1", "2"]

Chcemy maplistę ciągów odpowiadających im danych wyjściowychadd_one .

Na początek możemy zadzwonić

nums = arr.map(&:to_i)

To jest to samo co

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

Możesz zobaczyć Co oznacza mapa (i: nazwa) w Ruby? po więcej informacji na ten temat.

Jednak nie zadzwoni:

nums.map(&:add_one)

Dlaczego? Ponieważ liczby nie mają wbudowanej metody add_one. Więc dostaniesz NoMethodError.

Zamiast podawać tylko nazwę metody :add_one , możesz przekazać powiązaną metodę method(:add_one) :

nums.map(&method(:add_one))

Teraz, zamiast każdego num używany jako odbiornik dla add_onesposobu, będą one używane jako argumenty . Jest to zasadniczo to samo, co:

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

Aby podać inny przykład, porównaj następujące:

[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
max pleaner
źródło
Nitpick: Object#methodzwraca powiązane Method , a nie an UnboundMethod. Metoda jest powiązana z odbiornikiem, ponieważ wywołujesz ją w instancji, a zatem wie, co selfjest, podczas gdy Module#instance_methodzwraca a, UnboundMethodponieważ nie może wiedzieć, z którą instancją będzie używana.
Jörg W Mittag
@ JörgWMittag Ok, dziękuję za korektę, masz rację. Musiałem się z tym mieszać, .instance_methodponieważ właśnie przechodziłem przez (wadliwą) pamięć
max pleaner
10

method(:function)to wiadomość wysyłana (czasami nazywana wywołaniem metody ) do niejawnego odbiorcy (tj self.). Wysyła wiadomość methoddo niejawnego odbiorcy (tjself ), Przekazując :functionjako jedyny argument.

:function jest Symbol dosłowne, tzn. jest dosłowne oznaczenie Symbol. Symbolto typ danych reprezentujący „nazwę czegoś”.

Jednoargumentowy znak ampersand &operator „rozwija” a Procdo bloku . To znaczy, że możesz przejść tam, Procgdzie oczekiwany jest blok . Jeśli obiekt nie jest już a Proc, zostanie wysłany to_prockomunikat umożliwiający jego konwersję na Proc. (Operator jest dozwolony tylko na liście argumentów i tylko dla ostatniego argumentu. Jest podwójny z& podwójność sigil na liście parametrów, która „zwija” blok w Procobiekt.)

Procjest typem danych reprezentującym kod wykonywalny. Jest to podstawowa klasa biblioteki Ruby dla podprogramów pierwszej klasy.

To, co to robi, to wywołanie methodmetody selfz :functionargumentem, wywołanie to_procwartości zwracanej, „rozwinięcie” wynikowego Procobiektu do bloku i przekazanie tego bloku do wywołania integratetak, jakbyś napisał coś w rodzaju

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

methodMetoda jest tu najprawdopodobniej, Object#methodmetoda, która zwraca bound Method obiektu.

Podsumowując, jest to nieco równoważne

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

Ale wyrażone w tak zwanym stylu bez punktów .

Jörg W Mittag
źródło