Apa maksud dari `& metode (: fungsi)`?

15

Apa &method(:function)artinya Misalnya, saya punya baris ini:

res = integrate(0, 1, a, &method(:function))
RubyBeginner
sumber
Dua jawaban bagus (sejauh ini). Beruntunglah anda!
Cary Swoveland

Jawaban:

13

Katakanlah kita punya metode

def add_one(num)
  num + 1
end

dan berbagai string

arr = ["1", "2"]

Kami ingin mapdaftar string untuk output yang sesuai dari add_one.

Untuk memulai kita bisa menelepon

nums = arr.map(&:to_i)

Ini sama dengan

nums = arr.map do |str|
  str.to_i
end

Anda dapat melihat Apa artinya peta (&: nama) di Ruby? untuk info lebih lanjut tentang ini.

Namun, itu tidak berfungsi untuk memanggil:

nums.map(&:add_one)

Mengapa? Karena angka tidak memiliki metode bawaan add_one. Jadi, Anda akan mendapatkan NoMethodError.

Jadi, alih-alih hanya memberikan nama metode, :add_one Anda dapat melewati metode terikat method(:add_one) :

nums.map(&method(:add_one))

Sekarang, alih-alih setiap angka digunakan sebagai penerima untuk add_onemetode, mereka akan digunakan sebagai argumen . Jadi, pada dasarnya sama dengan:

nums.map do |num|
  add_one(num)
end

Untuk memberikan contoh lain, bandingkan yang berikut:

[1].map(&:puts)
# this is the same as [1].map { |num| num.puts }
# it raises NoMethodError

[1].map(&method(:puts))
# this is the same as [1].map { |num| puts num }
# it prints 1 successfully
pemohon maks
sumber
Nitpick: Object#methodmengembalikan sebuah batasan Method , bukan sebuah UnboundMethod. Metode ini terikat ke penerima karena Anda memanggilnya pada contoh dan dengan demikian tahu apa selfitu, sedangkan Module#instance_methodmengembalikan UnboundMethodkarena tidak bisa tahu apa yang akan digunakan dengan contoh itu.
Jörg W Mittag
@ JörgWMittag Ok terima kasih atas koreksinya, Anda benar saya pasti mencampurnya dengan .instance_methodkarena saya baru saja mengingat (cacat) memori
maks pleaner
10

method(:function)adalah pengiriman pesan (kadang-kadang disebut pemanggilan metode ) ke penerima implisit (yaitu self). Itu mengirim pesan methodke penerima implisit (yaitu self), lewat :functionsebagai satu-satunya argumen.

:functionadalah Symbolliteral, yaitu notasi literal dari a Symbol. Symboladalah tipe data yang mewakili "nama sesuatu".

The awers ampers uners dan &operator "membuka gulungan" a Procke dalam blok . Yaitu memungkinkan Anda untuk melewati di Procmana blok diharapkan. Jika objek belum menjadi Proc, maka akan dikirim to_procpesan yang memungkinkannya untuk mengubah dirinya menjadi a Proc. (Operator hanya sah dalam daftar argumen dan hanya untuk argumen terakhir. Ini adalah ganda dari& sigil dalam daftar parameter, yang "menggulung" blok ke Procobjek.)

Procadalah tipe data yang mewakili kode yang dapat dieksekusi. Ini adalah kelas inti perpustakaan Ruby untuk subrutin kelas satu.

Jadi, apa yang dilakukan, adalah memanggil methodmetode selfdengan :functionsebagai argumen, memanggil to_procnilai kembali, "membuka gulungan" Procobjek yang dihasilkan ke dalam blok dan meneruskan blok itu ke panggilan untuk integrateseolah-olah Anda telah menulis sesuatu seperti

res = integrate(0, 1, a) do
  # something
end

The methodMetode sini adalah kemungkinan besar, Object#methodmetode, yang mengembalikan terikat Method objek.

Jadi, secara keseluruhan, ini agak setara dengan

res = integrate(0, 1, a) do |*args, &block|
  function(*args, &block)
end

Namun diekspresikan dalam apa yang biasa disebut gaya pointfree .

Jörg W Mittag
sumber