Frage
Eine Antwort auf eine Frage, die ich gestern hier gestellt war das folgende Stück Ruby-Code:
def overlap?(r1,r2)
r1.include?(r2.begin) || r2.include?(r1.begin)
end
def any_overlap?(ranges)
ranges.sort_by(&:begin).each_cons(2).any? do |r1,r2|
overlap?(r1, r2)
end
end
ich each_cons
, aber was ist die seltsame &:begin
Schreibweise? Rette mich vor Syntax Hölle!
Danke!
Lösung
Wenn Sie das Präfix das letzte Argument eines Anrufs mit &
Sie machen deutlich, dass Sie einen Block senden und nicht ein normalen Argument. Ok, in method(&:something)
, :something
ist ein Symbol, keine proc , so Rubin automatisch ruft die Methode to_proc
einen echten Block zu erhalten. Und Rails Jungs (und jetzt auch Vanille Rubin) geschickt definiert als:
class Symbol
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
end
Das ist, warum Sie tun können:
>> [1, 2, 3].map(&:to_s) # instead of [1, 2, 3].map { |n| n.to_s }
=> ["1", "2", "3"]
[Bearbeiten] Hinweis: Wenn Sie feststellen, dass diese Konstruktion ist kein Syntatic Zucker, aber allgemeine Infrastruktur, dass Ruby bietet, nichts hält von Ihnen, Ihre eigenen to_proc
für andere Klassen implementieren. Nie fühlte begrenzt, weil &:method
keine Argumente erlaubt?
class Array
def to_proc
proc { |obj, *args| obj.send(*(self + args)) }
end
end
>> ["1", "F", "FF"].map(&[:to_i, 16])
=> [1, 15, 255]
Andere Tipps
my_method(&some_value)
Mittel my_method
aufzurufen, some_value
in dem speziellen Argument Schlitz vorbei, das proc-Slot, in der Regel reserviert für das Bestehen do-Notation Blöcke.
my_block = lambda { puts "hello" }
(1..3).each(&my_block)
Jedes Objekt, das ein Proc
ist oder die auf to_proc
reagiert erlaubt ist in dem proc-Slot übergeben werden. Wenn Sie in einem Objekt übergeben, das kein Proc
ist, aber reagiert auf to_proc
, dann to_proc
auf dem Objekt aufrufen für Sie Ruby und das Ergebnis in die Methode übergeben.
Die Implementierung von Symbol#to_proc
ist ein proc zurückzukehren, die, wenn ein Argument übergeben, das Argument sendet die Nachricht, dass das Symbol selbst ist. Zum Beispiel :hello.to_proc.call(my_obj)
werden bis zu tun my_obj.send :hello
beenden.
So my_array.each(&:hello)
geht :hello
zu each
im proc-Slot (wobei ein Block normalerweise übergeben würde, wenn Sie das tun-Notation verwendet, um einen Block zu machen). :hello.to_proc.call(my_array[0])
endet als my_array[0].send :hello
, und das gleiche für alle nachfolgenden Indizes von my_array
.
es gleich:
ranges.sort_by{|r| r.begin}