Sie kennen wahrscheinlich die folgende Ruby-Kurzform ( a
ist ein Array):
a.map(&:method)
Versuchen Sie beispielsweise Folgendes in irb:
>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]
Die Syntax a.map(&:class)
ist eine Abkürzung für a.map {|x| x.class}
.
Weitere Informationen zu dieser Syntax finden Sie unter " Was bedeutet map (&: name) in Ruby? ".
Über die Syntax führen &:class
Sie class
für jedes Array-Element einen Methodenaufruf durch.
Meine Frage ist: Können Sie dem Methodenaufruf Argumente liefern? Und wenn ja, wie?
Wie konvertieren Sie beispielsweise die folgende Syntax?
a = [1,3,5,7,9]
a.map {|x| x + 2}
zur &:
Syntax?
Ich behaupte nicht, dass die &:
Syntax besser ist. Ich interessiere mich nur für die Mechanik der Verwendung der &:
Syntax mit Argumenten.
Ich nehme an, Sie wissen, dass dies +
eine Methode für die Integer-Klasse ist. Sie können Folgendes in irb versuchen:
>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2
Symbol#with
es in der Kernbibliothek möglicherweise nicht vorhanden ist und die Definition dieser Methode weniger destruktiv ist als die Neudefinition einer vorhandenen Methode, ändert sich die Implementierung der Kernklasse der Ruby-Bibliothek immer noch (dh überschreibt sie). Die Übung sollte sehr sparsam und mit großer Vorsicht durchgeführt werden. \ n \ n Bitte erwägen Sie, von der vorhandenen Klasse zu erben und die neu erstellte Klasse zu ändern. Dies führt im Allgemeinen zu vergleichbaren Ergebnissen ohne die negativen Nebenwirkungen einer Änderung der Rubin-Kernklassen.Symbol
Klasse zu erben , ist dies nicht trivial (wenn überhaupt möglich), da es sich um eine solche Kernklasse handelt (es gibt beispielsweise keinenew
Methode), und ihre Verwendung ist umständlich (wenn überhaupt möglich), wodurch die Klasse besiegt wird Zweck der Erweiterung ... Wenn Sie eine Implementierung zeigen können, die dies nutzt und vergleichbare Ergebnisse erzielt, teilen Sie diese bitte mit!with
Methode zu definieren, definieren Siecall
. Dann können Sie Dinge tun, wiea.map(&:+.(2))
daobject.()
die#call
Methode verwendet. Und wenn Sie schon dabei sind, können Sie lustige Dinge schreiben wie:+.(2).(3) #=> 5
- fühlt sich irgendwie LISPY an, nein?Für Ihr Beispiel kann getan werden
a.map(&2.method(:+))
.So funktioniert es: -
2.method(:+)
gibt einMethod
Objekt. Dann&
, auf2.method(:+)
, tatsächlich eine Anruf -#to_proc
Methode, die es macht einProc
Objekt. Folgen Sie dann Wie nennt man den Operator &: in Ruby? .quelle
Pry
Ausgaben oben sehen, können Sie es bekommen, wie es funktioniert.+
es kommutativ ist.Wie der Beitrag, auf den Sie verlinkt haben, bestätigt,
a.map(&:class)
ist dies keine Abkürzung für,a.map {|x| x.class}
sondern füra.map(&:class.to_proc)
.Dies bedeutet, dass
to_proc
alles aufgerufen wird, was dem&
Operator folgt .Sie können es also direkt
Proc
eingeben:Ich weiß, dass dies höchstwahrscheinlich den Zweck Ihrer Frage zunichte macht, aber ich kann keinen anderen Weg sehen - es ist nicht so, dass Sie angeben, welche Methode aufgerufen werden soll, sondern nur etwas übergeben, auf das geantwortet wird
to_proc
.quelle
my_proc = Proc.new{|i| i + 1}
,[1,2,3,4].map(&my_proc) => [2,3,4,5]
Kurze Antwort: Nein.
Nach der Antwort von @ rkon können Sie auch Folgendes tun:
quelle
&->(_){_ + 2}
es kürzer ist als{|x| x + 2}
.Anstatt die Kernklassen wie in der akzeptierten Antwort selbst zu patchen, ist es kürzer und sauberer, die Funktionalität des Facetten-Edelsteins zu verwenden :
quelle
Es gibt eine andere native Option für Aufzählungen, die meiner Meinung nach nur für zwei Argumente hübsch ist. Die Klasse
Enumerable
hat die Methode,with_object
die dann eine andere zurückgibtEnumerable
.Sie können also den
&
Operator für eine Methode mit jedem Element und dem Objekt als Argumente aufrufen .Beispiel:
Wenn Sie mehr Argumente wollen, sollten Sie den Vorgang wiederholen, aber meiner Meinung nach ist es hässlich:
quelle
Ich bin mir nicht sicher über das
Symbol#with
bereits Gepostete, ich habe es ziemlich vereinfacht und es funktioniert gut:(verwendet auch
public_send
anstattsend
zu verhindern, dass private Methoden aufgerufen werden, wird auchcaller
bereits von Ruby verwendet, so dass dies verwirrend war)quelle