Was bedeutet "& method (: function)"?

15

Was heißt &method(:function)das Zum Beispiel habe ich diese Zeile:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
quelle
Zwei ausgezeichnete Antworten (bisher). Du Glückspilz!
Cary Swoveland

Antworten:

13

Angenommen, wir haben eine Methode

def add_one(num)
  num + 1
end

und eine Reihe von Zeichenfolgen

arr = ["1", "2"]

Wir wollen mapdie Liste der Strings zu ihren entsprechenden Ausgaben von add_one.

Zu Beginn können wir anrufen

nums = arr.map(&:to_i)

Das ist das Gleiche wie

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

Sie können sehen, was Karte (&: Name) in Ruby bedeutet. Weitere Informationen hierzu.

Es funktioniert jedoch nicht, Folgendes anzurufen:

nums.map(&:add_one)

Warum? Weil Zahlen keine eingebaute Methode haben add_one. So bekommen Sie eine NoMethodError.

Anstatt nur einen Methodennamen anzugeben :add_one , können Sie eine gebundene Methode übergeben method(:add_one) :

nums.map(&method(:add_one))

Anstatt dass jede Zahl als Empfänger für die add_oneMethode verwendet wird, werden sie jetzt als Argumente verwendet . Es ist also im Wesentlichen dasselbe wie:

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

Um ein weiteres Beispiel zu nennen, vergleichen Sie Folgendes:

[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
quelle
Nitpick: Gibt Object#methodeine Bindung zurück Method , keine UnboundMethod. Die Methode ist an einen Empfänger gebunden , weil Sie sie auf einer Instanz aufrufen und somit wissen, was sie selfist, während sie eine Module#instance_methodzurückgibt, UnboundMethodweil sie nicht wissen kann, mit welcher Instanz sie verwendet werden soll.
Jörg W Mittag
@ JörgWMittag Ok, danke für die Korrektur, du hast Recht, ich muss es verwechselt haben, .instance_methodweil ich gerade durch (fehlerhafte) Erinnerung
gegangen bin
10

method(:function)ist eine Nachricht, die an den impliziten Empfänger (dh ) gesendet wird (manchmal auch als Methodenaufruf bezeichnetself ). Es sendet die Nachricht methodan den impliziten Empfänger (dh self) und übergibt sie :functionals einziges Argument.

:functionist ein SymbolLiteral, dh es ist die wörtliche Notation von a Symbol. Symbolist ein Datentyp, der "den Namen von etwas" darstellt.

Der kaufmännische Und- &Operator mit unärem Präfix "rollt" a Procin einen Block ab . Dh es erlaubt Ihnen, einen zu übergeben, Procwo ein Block erwartet wird. Wenn das Objekt noch kein Objekt ist Proc, wird ihm die to_procNachricht gesendet , damit es sich selbst in ein Objekt konvertieren kann Proc. (Der Operator ist nur in einer Argumentliste legal und nur für das letzte Argument. Es ist das Dual des &Siegels in einer Parameterliste, das einen Block in ein ProcObjekt "rollt" .)

Procist ein Datentyp, der ausführbaren Code darstellt. Es ist Rubys Kernbibliotheksklasse für erstklassige Unterprogramme.

Rufen Sie also die methodMethode selfmit :functionals Argument auf, rufen Sie to_procden Rückgabewert auf, "rollen" Sie das resultierende ProcObjekt in einen Block ab und übergeben Sie diesen Block an den Aufruf an, integrateals hätten Sie so etwas geschrieben

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

Die methodMethode hier ist höchstwahrscheinlich die Object#methodMethode, die ein gebundenes Method Objekt zurückgibt .

Alles in allem ist dies also etwas äquivalent zu

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

Aber ausgedrückt in dem, was allgemein als punktfreier Stil bezeichnet wird .

Jörg W Mittag
quelle