Anda mungkin sudah familiar dengan singkatan Ruby berikut ( a
is an array):
a.map(&:method)
Misalnya, coba yang berikut ini di irb:
>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]
Sintaksnya a.map(&:class)
adalah singkatan dari a.map {|x| x.class}
.
Baca lebih lanjut tentang sintaks ini di " Apa arti map (&: name) di Ruby? ".
Melalui sintaks &:class
, Anda membuat panggilan metode class
untuk setiap elemen array.
Pertanyaan saya adalah: dapatkah Anda memberikan argumen ke pemanggilan metode? Dan jika ya, bagaimana caranya?
Misalnya, bagaimana Anda mengonversi sintaks berikut
a = [1,3,5,7,9]
a.map {|x| x + 2}
ke &:
sintaks?
Saya tidak menyarankan bahwa &:
sintaksnya lebih baik. Saya hanya tertarik pada mekanisme penggunaan &:
sintaks dengan argumen.
Saya berasumsi Anda tahu itu +
adalah metode pada kelas Integer. Anda dapat mencoba yang berikut di irb:
>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2
Symbol#with
mungkin tidak ada di pustaka inti dan mendefinisikan metode itu kurang merusak daripada mendefinisikan ulang metode yang sudah ada, itu masih mengubah (yaitu menimpa) implementasi kelas inti pustaka ruby. Latihan ini harus dilakukan dengan sangat hati-hati dan hati-hati. \ n \ n Harap pertimbangkan untuk mewarisi dari kelas yang sudah ada dan memodifikasi kelas yang baru dibuat. Ini umumnya mencapai hasil yang sebanding tanpa efek samping negatif dari perubahan kelas inti ruby.Symbol
kelas - itu tidak sepele (jika mungkin), karena ini adalah kelas inti (tidak memilikinew
metode, misalnya), dan penggunaannya akan rumit (jika mungkin), yang akan mengalahkan tujuan peningkatan ... jika Anda dapat menunjukkan implementasi yang menggunakan itu, dan mencapai hasil yang sebanding - silakan bagikan!with
metode, definisikancall
. Kemudian Anda dapat melakukan hal-hal sepertia.map(&:+.(2))
sejakobject.()
menggunakan#call
metode tersebut. Dan saat Anda melakukannya, Anda dapat menulis hal-hal menyenangkan seperti:+.(2).(3) #=> 5
- terasa seperti LISPy, bukan?Untuk contoh Anda bisa dilakukan
a.map(&2.method(:+))
.Inilah cara kerjanya: -
2.method(:+)
memberikan sebuahMethod
objek. Kemudian&
, pada2.method(:+)
, sebenarnya#to_proc
metode panggilan , yang membuatnya menjadiProc
objek. Kemudian ikuti Apa yang Anda sebut operator &: di Ruby? .sumber
Pry
output di atas, Anda bisa mendapatkannya, bagaimana cara kerjanya.+
bersifat komutatif.Seperti yang dikonfirmasi oleh postingan yang Anda tautkan,
a.map(&:class)
ini bukan singkatana.map {|x| x.class}
tapi untuka.map(&:class.to_proc)
.Ini berarti
to_proc
dipanggil apapun yang mengikuti&
operator.Jadi Anda bisa memberikannya secara langsung sebagai
Proc
gantinya:Saya tahu bahwa kemungkinan besar ini mengalahkan tujuan pertanyaan Anda, tetapi saya tidak dapat melihat jalan lain - bukan karena Anda menentukan metode mana yang akan dipanggil, Anda hanya meneruskan sesuatu yang merespons
to_proc
.sumber
my_proc = Proc.new{|i| i + 1}
,[1,2,3,4].map(&my_proc) => [2,3,4,5]
Jawaban singkatnya: Tidak.
Mengikuti jawaban @ rkon, Anda juga bisa melakukan ini:
sumber
&->(_){_ + 2}
ada yang lebih pendek dari{|x| x + 2}
.Alih-alih menambal kelas inti sendiri, seperti dalam jawaban yang diterima, lebih pendek dan lebih bersih untuk menggunakan fungsionalitas permata Facets :
sumber
Ada opsi asli lain untuk enumerables yang cukup hanya untuk dua argumen menurut saya. kelas
Enumerable
memiliki metodewith_object
yang kemudian mengembalikan yang lainEnumerable
.Jadi Anda bisa memanggil
&
operator untuk metode dengan setiap item dan objek sebagai argumen.Contoh:
Jika Anda menginginkan lebih banyak argumen, Anda harus mengulangi prosesnya tetapi menurut saya itu jelek:
sumber
Saya tidak yakin tentang yang
Symbol#with
sudah diposting, saya menyederhanakannya sedikit dan berfungsi dengan baik:(juga menggunakan
public_send
bukansend
untuk mencegah memanggil metode pribadi, jugacaller
sudah digunakan oleh ruby jadi ini membingungkan)sumber