InhaltsverzeichnisKlicke auf den Link, um zur gewünschten Stelle zu navigieren
Dieser Inhalt wurde automatisch aus dem Ukrainischen übersetzt.
Auf den ersten Blick scheint dieser Code seltsam - normalerweise schreiben wir map(&:to_s) oder map { |x| ... }. Aber Ruby erlaubt es, nicht nur Symbole, sondern auch beliebige Objekte nach & zu übergeben, wenn sie durch die Methode to_proc in ein Proc umgewandelt werden können.
Wenn Ruby &Person sieht, ruft es auf: Person.to_procDas bedeutet, es versucht, Person in ein Proc-Objekt umzuwandeln.
Das erhaltene Proc-Objekt wird als Block für die Methode map verwendet.
Dann ruft Ruby für jedes Element des Arrays dieses Proc auf - proc.call(element)
Beispiel
class Person
def initialize(name)
@name = name
end
def self.to_proc
->(name) { new(name) }
end
end
people = ["Bant", "Yuki", "Beanie"].map(&Person)
p people
Ergebnis:
[#<Person:0x0000000103f2b3a8 @name="Bant">, #<Person:0x0000000103f2b0b0 @name="Yuki">, #<Person:0x0000000103f2adb8 @name="Beanie">]
Was passiert wirklich im Hintergrund?
Ruby ruft Ihr Person.to_proc auf, das eine Lambda zurückgibt:
->(name) { Person.new(name) } # beachten Sie, dass wir in der Methode Person weggelassen haben (es ist nicht erforderlich, es anzugeben)
Und dann führt es tatsächlich dasselbe aus wie:
["Oleh", "Ira", "Marta"].map { |name| Person.new(name) }
Wie funktioniert .call?
Jeder Proc oder jede Lambda hat eine Methode .call, die den darin gespeicherten Code ausführt. Das heißt, wenn Ruby proc.call(element) macht, führt es tatsächlich Ihren Block aus:
my_proc = ->(x) { puts "Hallo, #{x}" }
my_proc.call("Ruby") # => "Hallo, Ruby"
Kurz gesagt:
- &obj in Ruby → ruft obj.to_proc auf.
- Das Ergebnis muss ein Proc oder eine Lambda sein.
- Dann ruft Ruby proc.call(x) für jedes Element auf.
- Deshalb funktioniert map(&Person) nur, wenn die Klasse die Methode self.to_proc hat.
Den letzten Punkt betrachten wir etwas genauer. Wenn die Klasse keine Methode .to_proc hat - erwarten Sie einen Fehler. Warum?
[1, 2, 3].map(&123)
Was Ruby tut:
- es sieht &123
- es denkt: “aha, ich muss 123.to_proc aufrufen”
- aber bei Zahlen (Integer) gibt es keine Methode to_proc
- also - Fehler
irb(main):001> 123.to_proc (irb):1:in `<main>': undefinierte Methode `to_proc' für 123:Integer (NoMethodError) 123.to_proc ^^^^^^^^ Meinten Sie? to_r from /Users/mykyta/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/irb-1.15.2/exe/irb:9:in `<top (required)>' from /Users/mykyta/.rbenv/versions/3.2.1/bin/irb:25:in `load' from /Users/mykyta/.rbenv/versions/3.2.1/bin/irb:25:in `<main>' irb(main):002>
Dieser Beitrag hat noch keine Ergänzungen vom Autor.