Znalazłem ten kod w RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Co robi (&:name)
w map(&:name)
średniej?
ruby
syntax
operators
parameter-passing
Collimarco
źródło
źródło
Odpowiedzi:
To jest skrót od
tags.map(&:name.to_proc).join(' ')
Jeśli
foo
jest to obiekt zto_proc
metodą, możesz przekazać ją do metody as&foo
, która wywoła jąfoo.to_proc
i użyje jako bloku metody.Symbol#to_proc
Metoda został dodany przez ActiveSupport ale został zintegrowany Ruby 1.8.7. To jest jego wdrożenie:źródło
&
, tj.tags.map(&:name.to_proc).join(' ')
Kolejny fajny skrót, nieznany wielu, to
co jest skrótem od
Dzwoniąc
method(:foo)
, wzięliśmyMethod
obiekt,self
który reprezentuje jegofoo
metodę, i użyliśmy&
do oznaczenia, że mato_proc
metodę, która konwertuje go naProc
.Jest to bardzo przydatne, gdy chcesz robić rzeczy bez punktów . Przykładem jest sprawdzenie, czy w tablicy jest jakikolwiek ciąg znaków, który jest taki sam
"foo"
. Istnieje konwencjonalny sposób:I jest sposób bez punktów:
Preferowany sposób powinien być najbardziej czytelny.
źródło
array.each{|e| foo(e)}
jest jeszcze krótszy :-) +1 tak czy inaczej&method
?[1,2,3].map(&Array.method(:new))
Jest to równoważne z
źródło
Zwróćmy też uwagę, że znaki handlowe i
#to_proc
magiczne mogą współpracować z dowolną klasą, nie tylko Symbolem. Wielu rubyistów decyduje się zdefiniować#to_proc
w klasie Array:Ampersand
&
działa poprzez wysyłanieto_proc
wiadomości na swoim operandzie, który w powyższym kodzie jest klasy Array. A ponieważ zdefiniowałem#to_proc
metodę na tablicy, linia staje się:źródło
To jest skrót od
tags.map { |tag| tag.name }.join(' ')
źródło
&
operator wołato_proc
swój operand. Więc nie jest to specyficzne dla metody map i faktycznie działa na każdej metodzie, która pobiera blok i przekazuje jeden lub więcej argumentów do bloku.jest taki sam jak
&:name
po prostu używa symbolu jako nazwy metody, która ma zostać wywołana.źródło
Odpowiedź Josha Lee jest prawie poprawna, tyle że równoważny kod Ruby powinien wyglądać następująco.
nie
Z tym kodem, gdy
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
jest wykonywany, Ruby dzieli pierwsze wejście[1,'a']
na 1 i „a”, aby daćobj
1 iargs*
„a”, aby spowodować błąd, ponieważ obiekt Fixnum 1 nie ma metody self (która jest: pierwsza).Kiedy
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
jest wykonywany;:first
jest obiektem Symbol, więc po&:first
podaniu metody mapy jako parametru wywoływany jest Symbol # to_proc.map wysyła komunikat wywołania do: first.to_proc z parametrem
[1,'a']
, np.:first.to_proc.call([1,'a'])
jest wykonywany.Procedura to_proc w klasie Symbol wysyła komunikat wysyłania do obiektu tablicy (
[1,'a']
) z parametrem (: first), np.[1,'a'].send(:first)
jest wykonywany.wykonuje iterację nad resztą elementów w
[[1,'a'],[2,'b'],[3,'c']]
obiekcie.Jest to to samo, co wykonywanie
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
wyrażenia.źródło
[1,2,3,4,5,6].inject(&:+)
- zastrzyk oczekuje lambdy z dwoma parametrami (notka i przedmiot) i:+.to_proc
dostarcza ją -Proc.new |obj, *args| { obj.send(self, *args) }
lub{ |m, o| m.+(o) }
Działają się tutaj dwie rzeczy i ważne jest, aby zrozumieć oba.
Jak opisano w innych odpowiedziach,
Symbol#to_proc
metoda jest wywoływana.Ale powodem
to_proc
wywołania tego symbolu jest to, że jest przekazywanymap
jako argument blokowy. Umieszczenie&
przed argumentem w wywołaniu metody powoduje, że jest on przekazywany w ten sposób. Dotyczy to każdej metody Ruby, nie tylkomap
symboli.Symbol
Zostaje zamieniana naProc
ponieważ jest przekazywana w postaci bloku. Możemy to pokazać, próbując przekazać procesor.map
bez znaku handlowego:Mimo że nie trzeba go konwertować, metoda nie będzie wiedziała, jak go użyć, ponieważ oczekuje argumentu blokowego. Podanie go
&
daje oczekiwany.map
blok.źródło
(&: name) to skrót od (&: name.to_proc), to samo co
tags.map{ |t| t.name }.join(' ')
to_proc jest faktycznie zaimplementowane w C.
źródło
mapa (i: nazwa) pobiera wymienny obiekt (tagi w twoim przypadku) i uruchamia metodę name dla każdego elementu / tagu, wypisując każdą zwróconą wartość z metody.
To jest skrót od
która zwraca tablicę nazw elementów (tagów)
źródło
Zasadniczo wykonuje wywołanie metody
tag.name
dla każdego znacznika w tablicy.Jest to uproszczony rubinowy skrót.
źródło
Chociaż mamy już świetne odpowiedzi, patrząc z perspektywy początkującego chciałbym dodać dodatkowe informacje:
Oznacza to, że przekazujesz inną metodę jako parametr do funkcji mapy. (W rzeczywistości podajesz symbol, który zamienia się w proc. Ale to nie jest tak ważne w tym konkretnym przypadku).
Ważne jest to, że masz
method
nazwę,name
która będzie używana przez metodę map jako argument zamiast tradycyjnegoblock
stylu.źródło
Po pierwsze,
&:name
jest skrótem do&:name.to_proc
, w którym:name.to_proc
zwracaProc
(coś, co jest podobne, ale nie identyczne jak lambda), które po wywołaniu z obiektem jako (pierwszy) argument wywołujename
metodę na tym obiekcie.Po drugie, podczas gdy
&
wdef foo(&block) ... end
konwertuje blok przekazany nafoo
aProc
, robi się odwrotnie, gdy jest stosowany do aProc
.Zatem
&:name.to_proc
jest blok, który przyjmuje obiekt jako argument i wywołuje na nimname
metodę, tj{ |o| o.name }
.źródło
Oto
:name
symbol wskazujący na metodęname
znacznika obiektu. Kiedy przechodzimy&:name
domap
, będzie traktowanyname
jako obiekt proc. W skrócietags.map(&:name)
działa jako:źródło
to znaczy
źródło
To jest tak samo jak poniżej:
źródło