Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
```html
```
Na pierwszy rzut oka taki kod wydaje się dziwny - zazwyczaj piszemy map(&:to_s) lub map { |x| ... }. Ale Ruby pozwala przekazywać nie tylko symbole, ale i dowolne obiekty po &, jeśli mogą zostać przekształcone na Proc za pomocą metody to_proc.
Kiedy Ruby widzi &Person, wywołuje: Person.to_procTo znaczy, że próbuje przekształcić Person w obiekt Proc.
Uzyskany obiekt Proc jest używany jako blok dla metody map.
Następnie Ruby dla każdego elementu tablicy wywołuje ten Proc - proc.call(element)
Przykład
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
Wynik:
[#<Person:0x0000000103f2b3a8 @name="Bant">, #<Person:0x0000000103f2b0b0 @name="Yuki">, #<Person:0x0000000103f2adb8 @name="Beanie">]
Co tak naprawdę dzieje się pod maską?
Ruby wywołuje twój Person.to_proc, który zwraca lambdę:
->(name) { Person.new(name) } # zauważ, że w metodzie pominęliśmy Person (nie trzeba podawać)
I następnie faktycznie wykonuje to samo, co:
["Oleh", "Ira", "Marta"].map { |name| Person.new(name) }
Jak działa .call?
Każdy Proc lub lambda ma metodę .call, która uruchamia zapisany wewnątrz kod. To znaczy, że kiedy Ruby wykonuje proc.call(element), faktycznie wykonuje twój blok:
my_proc = ->(x) { puts "Hello, #{x}" }
my_proc.call("Ruby") # => "Hello, Ruby"
Krótko mówiąc:
- &obj w Ruby → wywołuje obj.to_proc.
- Wynik musi być Proc lub lambda.
- Następnie Ruby wywołuje proc.call(x) dla każdego elementu.
- Dlatego map(&Person) działa, jeśli klasa ma metodę self.to_proc.
Ostatni punkt omówimy nieco dokładniej. Jeśli klasa nie ma metody .to_proc - oczekuj błędu. Dlaczego?
[1, 2, 3].map(&123)
Co robi Ruby:
- widzi &123
- myśli: “aha, trzeba wywołać 123.to_proc”
- ale w liczbach (Integer) nie ma metody to_proc
- więc - błąd
irb(main):001> 123.to_proc (irb):1:in `<main>': undefined method `to_proc' for 123:Integer (NoMethodError) 123.to_proc ^^^^^^^^ Did you mean? 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>
Ten post nie ma jeszcze żadnych dodatków od autora.