Co oznacza map ( & : name) W Rubim?
Znalazłem ten kod w A RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Co oznacza (&:name)
w map(&:name)
?
14 answers
To skrót od tags.map(&:name.to_proc).join(' ')
Jeśli foo
jest obiektem z metodą to_proc
, możesz przekazać go do metody jako &foo
, która wywoła foo.to_proc
i użyje go jako bloku metody.
Metoda Symbol#to_proc
została pierwotnie dodana przez ActiveSupport, ale została zintegrowana z Rubim 1.8.7. Jest to jego realizacja:
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-27 16:43:12
Kolejnym fajnym skrótem, nieznanym wielu, jest
array.each(&method(:foo))
Który jest skrótem
array.each { |element| foo(element) }
Wywołując method(:foo)
wzięliśmy obiekt Method
z self
, który reprezentuje jego metodę foo
, i użyliśmy &
, aby zaznaczyć, że ma to_proc
metoda , która przekształca ją w Proc
.
Jest to bardzo przydatne, gdy chcesz robić rzeczy styl bez punktów. Przykładem jest sprawdzenie, czy w tablicy znajduje się łańcuch równy łańcuchowi "foo"
. Jest sposób konwencjonalny:
["bar", "baz", "foo"].any? { |str| str == "foo" }
I jest sposób bez punktów:
["bar", "baz", "foo"].any?(&"foo".method(:==))
Preferowany sposób powinien być najbardziej czytelny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-09 18:44:35
Jest odpowiednikiem
def tag_names
@tag_names || tags.map { |tag| tag.name }.join(' ')
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 17:39:52
Zauważmy również, że Ampersand #to_proc
magia może działać z dowolną klasą, nie tylko symbolem. Wielu Rubyistów decyduje się zdefiniować #to_proc
w klasie tablicy:
class Array
def to_proc
proc { |receiver| receiver.send *self }
end
end
# And then...
[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]
Ampersand &
działa poprzez wysłanie to_proc
wiadomości na swoim operandu, który w powyższym kodzie należy do klasy Array. A ponieważ zdefiniowałem metodę #to_proc
na tablicy, linia staje się:
[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-05 19:28:18
To skrót od tags.map { |tag| tag.name }.join(' ')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 18:06:00
tags.map(&:name)
Jest tym samym co
tags.map{|tag| tag.name}
&:name
po prostu używa symbolu jako nazwy metody do wywołania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-01 03:23:29
Odpowiedź Josha Lee jest prawie poprawna, z wyjątkiem tego, że odpowiedni kod Ruby powinien być następujący.
class Symbol
def to_proc
Proc.new do |receiver|
receiver.send self
end
end
end
Nie
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
Z tym kodem, gdy print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
jest wykonywane, Ruby dzieli pierwsze wejście [1,'a']
na 1 i 'a', aby dać obj
1 i args*
'a', aby spowodować błąd, ponieważ obiekt Fixnum 1 nie ma metody self (która jest :first).
Kiedy [[1,'a'],[2,'b'],[3,'c']].map(&:first)
jest wykonywane;
:first
jest obiektem symbolicznym, więc gdy&:first
jest dana metodzie map jako parametr, Symbol#to_proc jest wywoływany.Map wysyła wiadomość 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 wiadomość do obiektu array (
[1,'a']
) z parametrem (:first), np. jest wykonywana[1,'a'].send(:first)
.Iteracja nad resztą elementów w obiekcie
[[1,'a'],[2,'b'],[3,'c']]
.
Jest to to samo co wykonywanie [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
wyrażenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 21:14:16
Dzieją się tu dwie rzeczy i ważne jest, aby zrozumieć obie.
Jak opisano w innych odpowiedziach, Metoda Symbol#to_proc
jest wywoływana.
Ale powodem wywołania symbolu jest to, że jest on przekazywany do map
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 tylko map
z symbolami.
def some_method(*args, &block)
puts "args: #{args.inspect}"
puts "block: #{block.inspect}"
end
some_method(:whatever)
# args: [:whatever]
# block: nil
some_method(&:whatever)
# args: []
# block: #<Proc:0x007fd23d010da8>
some_method(&"whatever")
# TypeError: wrong argument type String (expected Proc)
# (String doesn't respond to #to_proc)
Symbol
zostaje zamienione na Proc
, ponieważ jest przeszedł jako blok. Możemy to pokazać, próbując przekazać proc do .map
bez ampersand:
arr = %w(apple banana)
reverse_upcase = proc { |i| i.reverse.upcase }
reverse_upcase.is_a?(Proc)
=> true
arr.map(reverse_upcase)
# ArgumentError: wrong number of arguments (1 for 0)
# (map expects 0 positional arguments and one block argument)
arr.map(&reverse_upcase)
=> ["ELPPA", "ANANAB"]
Mimo że nie trzeba go przekonwertować, metoda nie będzie wiedziała, jak go użyć, ponieważ oczekuje argumentu blokowego. Podanie go z &
daje .map
oczekiwany blok.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-09 01:43:55
( & : name) jest skrótem od ( & : name.to_proc) jest taki sam jak tags.map{ |t| t.name }.join(' ')
To_proc jest faktycznie zaimplementowany w C
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-11 05:55:00
Chociaż mamy już świetne odpowiedzi, patrząc z perspektywy początkującego, chciałbym dodać dodatkowe informacje:
Co oznacza map ( & : name) W Rubim?
Oznacza to, że przekazujesz inną metodę jako parametr do funkcji map. (W rzeczywistości przekazujesz symbol, który zostaje przekształcony w proc. Ale to nie jest tak ważne w tym konkretnym przypadku).
Ważne jest to, że masz method
o nazwie name
, która będzie używana za pomocą metody map jako argumentu zamiast tradycyjnego stylu block
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-08 15:45:53
Tutaj :name
jest symbolem wskazującym na metodę name
obiektu tag.
Kiedy przechodzimy &:name
do map
, będzie on traktował {[2] } jako obiekt proc.
W skrócie, tags.map(&:name)
działa jak:
tags.map do |tag|
tag.name
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 06:30:44
Oznacza
array.each(&:to_sym.to_proc)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-20 12:25:09
Jest taki sam jak poniżej:
def tag_names
if @tag_names
@tag_names
else
tags.map{ |t| t.name }.join(' ')
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-27 09:32:18
Map ( & : name) pobiera obiekt zliczalny (w Twoim przypadku znaczniki) i uruchamia metodę name dla każdego elementu/znacznika, wyprowadzając każdą zwracaną wartość z metody.
Jest skrótem
array.map { |element| element.name }
Który zwraca tablicę nazw elementów (znaczników)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-01 04:48:06