Saya menemukan kode ini di RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Apa yang (&:name)
di map(&:name)
berarti?
ruby
syntax
operators
parameter-passing
collimarco
sumber
sumber
Jawaban:
Ini singkatan untuk
tags.map(&:name.to_proc).join(' ')
Jika
foo
objek denganto_proc
metode, maka Anda bisa meneruskannya ke metode sebagai&foo
, yang akan memanggilfoo.to_proc
dan menggunakannya sebagai blok metode.The
Symbol#to_proc
Metode ini awalnya ditambahkan oleh ActiveSupport tetapi telah diintegrasikan ke dalam Ruby 1.8.7. Ini implementasinya:sumber
&
, yaitutags.map(&:name.to_proc).join(' ')
Steno keren lainnya, tidak diketahui banyak orang, adalah
yang merupakan singkatan untuk
Dengan memanggil
method(:foo)
kita mengambilMethod
objek dariself
yang mewakilifoo
metodenya, dan menggunakan&
untuk menandakan bahwa ia memilikito_proc
metode yang mengubahnya menjadi aProc
.Ini sangat berguna ketika Anda ingin melakukan hal - hal gaya point-free . Contohnya adalah untuk memeriksa apakah ada string dalam array yang sama dengan string
"foo"
. Ada cara konvensional:Dan ada cara bebas-point:
Cara yang disukai harus yang paling mudah dibaca.
sumber
array.each{|e| foo(e)}
masih lebih pendek :-) +1 lagian&method
?[1,2,3].map(&Array.method(:new))
Ini setara dengan
sumber
Sementara mari kita perhatikan juga bahwa ampersand
#to_proc
magic dapat bekerja dengan semua kelas, bukan hanya Symbol. Banyak Rubyist memilih untuk mendefinisikan#to_proc
pada kelas Array:Ampersand
&
bekerja dengan mengirimto_proc
pesan pada operannya, yang, dalam kode di atas, adalah dari kelas Array. Dan karena saya mendefinisikan#to_proc
metode pada Array, barisnya menjadi:sumber
Ini singkatan untuk
tags.map { |tag| tag.name }.join(' ')
sumber
&
operator unary memanggilto_proc
operannya. Jadi itu tidak spesifik untuk metode peta, dan pada kenyataannya bekerja pada metode apa pun yang mengambil blok dan melewati satu atau lebih argumen ke blok.sama dengan
&:name
hanya menggunakan simbol sebagai nama metode untuk dipanggil.sumber
Jawaban Josh Lee hampir benar kecuali bahwa kode Ruby yang setara seharusnya adalah sebagai berikut.
tidak
Dengan kode ini, ketika
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
dijalankan, Ruby membagi input pertama[1,'a']
menjadi 1 dan 'a' untuk memberikanobj
1 danargs*
'a' untuk menyebabkan kesalahan karena objek Fixnum 1 tidak memiliki metode sendiri (yaitu: pertama).Kapan
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
dieksekusi;:first
adalah objek Simbol, jadi ketika&:first
diberikan kepada metode peta sebagai parameter, Simbol # to_proc dipanggil.map mengirim pesan panggilan ke: first.to_proc dengan parameter
[1,'a']
, mis:first.to_proc.call([1,'a'])
. dijalankan.prosedur to_proc di kelas Simbol mengirimkan pesan kirim ke objek array (
[1,'a']
) dengan parameter (: pertama), misalnya,[1,'a'].send(:first)
dijalankan.iterates atas sisa elemen dalam
[[1,'a'],[2,'b'],[3,'c']]
objek.Ini sama dengan mengeksekusi
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
ekspresi.sumber
[1,2,3,4,5,6].inject(&:+)
- menyuntikkan mengharapkan lambda dengan dua parameter (memo dan item) dan:+.to_proc
mengirimkannya -Proc.new |obj, *args| { obj.send(self, *args) }
atau{ |m, o| m.+(o) }
Ada dua hal yang terjadi di sini, dan penting untuk memahami keduanya.
Seperti dijelaskan dalam jawaban lain,
Symbol#to_proc
metode ini dipanggil.Tapi alasannya
to_proc
dipanggil pada simbol adalah karena dilewatkanmap
sebagai argumen blok. Menempatkan&
di depan argumen dalam pemanggilan metode menyebabkannya diteruskan dengan cara ini. Ini berlaku untuk metode Ruby apa pun, tidak hanyamap
dengan simbol.Akan
Symbol
dikonversi keProc
karena dilewatkan sebagai blok. Kami dapat menunjukkan ini dengan mencoba meneruskan proc ke.map
tanpa ampersand:Meskipun tidak perlu dikonversi, metode ini tidak akan tahu bagaimana menggunakannya karena mengharapkan argumen blok. Melewati dengan
&
memberi.map
blok yang diharapkannya.sumber
(&: name) adalah kependekan dari (&: name.to_proc) sama dengan
tags.map{ |t| t.name }.join(' ')
to_proc sebenarnya diimplementasikan dalam C
sumber
peta (&: nama) mengambil objek enumerable (memberi tag pada kasus Anda) dan menjalankan metode nama untuk setiap elemen / tag, menghasilkan setiap nilai yang dikembalikan dari metode.
Ini adalah singkatan untuk
yang mengembalikan array nama elemen (tag)
sumber
Ini pada dasarnya menjalankan pemanggilan metode
tag.name
pada setiap tag dalam array.Ini adalah steno ruby yang disederhanakan.
sumber
Meskipun kami sudah memiliki jawaban yang luar biasa, melihat melalui perspektif seorang pemula saya ingin menambahkan informasi tambahan:
Ini berarti, bahwa Anda meneruskan metode lain sebagai parameter ke fungsi peta. (Pada kenyataannya Anda melewati simbol yang akan dikonversi menjadi proc. Tapi ini tidak begitu penting dalam kasus khusus ini).
Yang penting adalah Anda memiliki
method
namaname
yang akan digunakan oleh metode peta sebagai argumen alih-alihblock
gaya tradisional .sumber
Pertama,
&:name
adalah jalan pintas untuk&:name.to_proc
, di mana:name.to_proc
mengembalikanProc
(sesuatu yang mirip, tetapi tidak identik dengan lambda) yang ketika dipanggil dengan objek sebagai argumen (pertama), memanggilname
metode pada objek itu.Kedua, sementara
&
didef foo(&block) ... end
mualaf blok diteruskan kefoo
keProc
, itu tidak sebaliknya bila diterapkan padaProc
.Dengan demikian,
&:name.to_proc
adalah blok yang mengambil objek sebagai argumen dan memanggilname
metode di atasnya, yaitu{ |o| o.name }
.sumber
Berikut
:name
adalah simbol yang menunjuk ke metodename
objek tag. Ketika kita beralih&:name
kemap
, itu akan memperlakukanname
sebagai objek proc. Singkatnya,tags.map(&:name)
bertindak sebagai:sumber
itu berarti
sumber
Sama seperti di bawah ini:
sumber