Lihat juga: buku Bahasa Pemrograman Ruby oleh Matz dan Flanagan, telah membahas topik ini secara komprehensif. proc berperilaku seperti semantik hasil blok, sedangkan lambda berperilaku seperti metode - metode memanggil semantik. Juga kembali, istirahat, dan sebagainya. semua berperilaku berbeda dalam procs n lambdas
Anda telah menerima jawaban yang hanya mengatakan apa perbedaan antara proc dan lambda, sedangkan judul pertanyaan Anda adalah kapan harus menggunakan hal-hal itu
Shri
Jawaban:
378
Perbedaan penting lainnya yang tidak kentara antara procs yang dibuat dengan lambdadan procs yang dibuat Proc.newadalah bagaimana mereka menangani returnpernyataan:
Dalam lambdaproc yang dibuat, returnpernyataan hanya mengembalikan dari proc itu sendiri
Dalam Proc.newproc yang dibuat, returnpernyataan itu sedikit lebih mengejutkan: ia mengembalikan kontrol tidak hanya dari proc, tetapi juga dari metode yang melampirkan proc!
Inilah lambda-pro yang dibuat returndalam aksi. Berperilaku dengan cara yang mungkin Anda harapkan:
def whowouldwin
mylambda = lambda {return"Freddy"}
mylambda.call
# mylambda gets called and returns "Freddy", and execution# continues on the next linereturn"Jason"end
whowouldwin
#=> "Jason"
Sekarang inilah Proc.newproc yang dibuat returnmelakukan hal yang sama. Anda akan melihat salah satu kasus di mana Ruby melanggar Prinsip Least Surprise yang banyak dibanggakan:
def whowouldwin2
myproc =Proc.new {return"Freddy"}
myproc.call
# myproc gets called and returns "Freddy", # but also returns control from whowhouldwin2!# The line below *never* gets executed.return"Jason"end
whowouldwin2
#=> "Freddy"
Berkat perilaku ini mengejutkan (serta kurang mengetik), saya cenderung untuk mendukung menggunakan lambdalebih Proc.newketika membuat procs.
@mattdipasquale Dalam tes saya, procbertindak suka lambdadan tidak suka Proc.newsehubungan dengan pernyataan pengembalian. Itu berarti ruby doc tidak akurat.
Kelvin
31
@mattdipasquale Maaf saya hanya setengah benar. procbertindak seperti lambdadi 1.8, tetapi bertindak seperti Proc.newdi 1.9. Lihat jawaban Peter Wagenet.
Kelvin
55
Mengapa perilaku "mengejutkan" ini? A lambdaadalah metode anonim. Karena ini adalah metode, ia mengembalikan nilai, dan metode yang menyebutnya dapat melakukan apa pun yang diinginkannya, termasuk mengabaikannya dan mengembalikan nilai yang berbeda. A Procseperti menempelkan dalam cuplikan kode. Itu tidak bertindak seperti metode. Jadi ketika pengembalian terjadi di dalam Proc, itu hanya bagian dari kode metode yang memanggilnya.
Arcolye
96
Untuk memberikan klarifikasi lebih lanjut:
Joey mengatakan bahwa perilaku pengembalian Proc.newmengejutkan. Namun ketika Anda menganggap bahwa Proc.new berperilaku seperti blok, ini tidak mengherankan karena itulah persisnya perilaku blok. lambas di sisi lain berperilaku lebih seperti metode.
Ini sebenarnya menjelaskan mengapa Procs fleksibel ketika datang ke arity (jumlah argumen) sedangkan lambda tidak. Blok tidak memerlukan semua argumen mereka diberikan tetapi metode melakukannya (kecuali jika standar disediakan). Meskipun memberikan argumen lambda default bukanlah pilihan di Ruby 1.8, sekarang didukung di Ruby 1.9 dengan sintaks alternatif lambda (seperti yang dicatat oleh webmat):
Dan Michiel de Mare (OP) salah tentang Procs dan lambda berperilaku sama dengan arity di Ruby 1.9. Saya telah memverifikasi bahwa mereka masih mempertahankan perilaku dari 1,8 seperti yang ditentukan di atas.
breakpernyataan sebenarnya tidak masuk akal baik dalam Procs atau lambdas. Dalam Procs, break akan mengembalikan Anda dari Proc.new yang telah selesai. Dan tidak masuk akal untuk melepaskan diri dari lambda karena pada dasarnya ini adalah metode, dan Anda tidak akan pernah melepaskan diri dari level teratas metode.
next,, redodan raiseberperilaku sama dalam Procs dan lambdas. Padahal retrytidak diperbolehkan di keduanya dan akan memunculkan eksepsi.
Dan akhirnya, procmetode ini tidak boleh digunakan karena tidak konsisten dan memiliki perilaku yang tidak terduga. Di Ruby 1.8 sebenarnya mengembalikan lambda! Di Ruby 1.9 ini telah diperbaiki dan mengembalikan Proc. Jika Anda ingin membuat Proc, tetap dengan Proc.new.
Untuk informasi lebih lanjut, saya sangat merekomendasikan O'Reilly The Ruby Programming Language yang merupakan sumber saya untuk sebagian besar informasi ini.
"" "Namun ketika Anda menganggap bahwa Proc.new berperilaku seperti sebuah blok, ini tidak mengherankan karena itulah persisnya perilaku balok." "" <- blok adalah bagian dari suatu objek, sementara Proc.new menciptakan sebuah objek. Baik lambda dan Proc.new menciptakan objek yang kelasnya adalah Proc, mengapa berbeda?
lemah
1
Pada Ruby 2.5, breakdari Procs menimbulkan LocalJumpError, sedangkan breakdari lambdas berperilaku seperti return( yaitu , return nil).
Masa Sakano
43
Saya menemukan halaman ini yang menunjukkan apa perbedaan antara Proc.newdan lambda. Menurut halaman, satu-satunya perbedaan adalah bahwa lambda ketat tentang jumlah argumen yang diterimanya, sedangkan Proc.newmengkonversi argumen yang hilang menjadi nil. Berikut adalah contoh sesi IRB yang menggambarkan perbedaan:
irb (utama): 001: 0> l = lambda {| x, y | x + y}
=> # <Proc: 0x00007fc605ec0748 @ (irb): 1>
irb (main): 002: 0> p = Proc.new {| x, y | x + y}
=> # <Proc: 0x00007fc605ea8698 @ (irb): 2>
irb (utama): 003: 0> l.call "hello", "world"
=> "helloworld"
irb (utama): 004: 0> p.call "hello", "world"
=> "helloworld"
irb (utama): 005: 0> l.call "hello"
ArgumentError: jumlah argumen yang salah (1 untuk 2)
dari (irb): 1
from (irb): 5: in `call '
dari (irb): 5
dari: 0
irb (utama): 006: 0> p.call "hello"
TypeError: tidak dapat mengonversi nil menjadi String
dari (irb): 2: dalam `+ '
dari (irb): 2
from (irb): 6: in `call '
dari (irb): 6
dari: 0
Halaman ini juga merekomendasikan penggunaan lambda kecuali Anda secara spesifik menginginkan perilaku toleran kesalahan. Saya setuju dengan sentimen ini. Menggunakan lambda tampaknya sedikit lebih ringkas, dan dengan perbedaan yang tidak signifikan, tampaknya pilihan yang lebih baik dalam situasi rata-rata.
Adapun Ruby 1.9, maaf, saya belum melihat ke 1.9, tapi saya tidak membayangkan mereka akan banyak mengubahnya (jangan menuruti kata saya untuk itu, sepertinya Anda telah mendengar beberapa perubahan, jadi Saya mungkin salah di sana).
Saya tidak bisa bicara banyak tentang perbedaan yang halus. Namun, saya dapat menunjukkan bahwa Ruby 1.9 sekarang memungkinkan parameter opsional untuk lambdas dan blok.
Berikut sintaks baru untuk lambdas yang stabby di bawah 1.9:
stabby =->(msg='inside the stabby lambda'){ puts msg }
Ruby 1.8 tidak memiliki sintaks itu. Cara konvensional mendeklarasikan block / lambdas juga tidak mendukung argumen opsional:
# under 1.8
l = lambda {|msg ='inside the stabby lambda'| puts msg }SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or'['or'.'
l = lambda {|msg ='inside the stabby lambda'| puts msg }
Namun, Ruby 1.9 mendukung argumen opsional bahkan dengan sintaks lama:
l = lambda {|msg ='inside the regular lambda'| puts msg }#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')#=> jeez
Jika Anda ingin membangun Ruby1.9 untuk Leopard atau Linux, lihat artikel ini (promosi mandiri yang tidak tahu malu).
Params opsional di dalam lambda sangat dibutuhkan, saya senang mereka menambahkannya di 1.9. Saya berasumsi blok juga dapat memiliki parameter opsional juga (dalam 1.9)?
mpd
Anda tidak mendemonstrasikan parameter default dalam blok, hanya lambdas
iconoclast
11
Jawaban singkat: Yang penting adalah apa yang returndilakukan: lambda kembali dengan sendirinya, dan proc kembali dari dirinya sendiri DAN fungsi yang memanggilnya.
Yang kurang jelas adalah mengapa Anda ingin menggunakan masing-masing. lambda adalah apa yang kita harapkan harus dilakukan dalam pengertian pemrograman fungsional. Ini pada dasarnya merupakan metode anonim dengan lingkup saat ini secara otomatis terikat. Dari keduanya, lambda adalah yang mungkin harus Anda gunakan.
Proc, di sisi lain, sangat berguna untuk mengimplementasikan bahasa itu sendiri. Misalnya, Anda dapat menerapkan pernyataan "jika" atau "untuk" loop dengannya. Setiap pengembalian yang ditemukan dalam proc akan kembali dari metode yang memanggilnya, bukan hanya pernyataan "jika". Beginilah cara kerja bahasa, bagaimana pernyataan "jika" bekerja, jadi tebakan saya adalah Ruby menggunakan ini di balik selimut dan mereka hanya mengeksposnya karena sepertinya kuat.
Anda hanya benar-benar membutuhkan ini jika Anda membuat konstruksi bahasa baru seperti loop, konstruksi if-else, dll.
"lambda kembali dari dirinya sendiri, dan proc kembali dari dirinya sendiri DAN fungsi yang menyebutnya" jelas salah dan kesalahpahaman yang sangat umum. Proc adalah penutupan dan pengembalian dari metode yang membuatnya. Lihat jawaban lengkap saya di bagian lain halaman ini.
ComDubh
10
Cara yang baik untuk melihatnya adalah bahwa lambda dieksekusi dalam ruang lingkup mereka sendiri (seolah-olah itu adalah pemanggilan metode), sementara Procs dapat dilihat sebagai dieksekusi sesuai dengan metode pemanggilan, setidaknya itu adalah cara yang baik untuk memutuskan mana yang akan digunakan dalam setiap kasus.
Matz telah menyatakan bahwa dia berencana untuk mencabutnya karena membingungkan memiliki proc dan Proc. Baru mengembalikan hasil yang berbeda. Pada 1.9 mereka berperilaku sama (proc adalah alias untuk Proc.new). eigenclass.org/hiki/Changes+in+Ruby+1.9#l47
Dave Rapin
@banister: procmengembalikan lambda dalam 1,8; sekarang telah diperbaiki untuk mengembalikan proc di 1.9 - namun ini merupakan perubahan besar; karenanya tidak direkomendasikan untuk digunakan lagi
Gishu
Saya pikir beliung mengatakan dalam catatan kaki di suatu tempat bahwa proc secara efektif terdeparasi atau sesuatu. Saya tidak memiliki nomor halaman yang tepat.
dertoni
7
Penutupan di Ruby adalah gambaran umum yang bagus untuk bagaimana blok, lambda dan proc bekerja di Ruby, dengan Ruby.
Saya berhenti membaca ini setelah saya membaca "suatu fungsi tidak dapat menerima banyak blok - melanggar prinsip bahwa penutupan dapat diedarkan secara bebas sebagai nilai." Blok bukan penutup. Procs adalah, dan suatu fungsi dapat menerima beberapa procs.
ComDubh
5
lambda berfungsi seperti yang diharapkan, seperti dalam bahasa lain.
Kabelnya Proc.newmengejutkan dan membingungkan.
The returnpernyataan dalam proc dibuat oleh Proc.newtidak hanya akan mengembalikan kontrol hanya dari dirinya sendiri, tetapi juga dari metode melampirkan itu .
def some_method
myproc =Proc.new {return"End."}
myproc.call
# Any code below will not get executed!# ...end
Anda bisa membantah bahwa Proc.newmemasukkan kode ke dalam metode melampirkan, seperti halnya blok. Tetapi Proc.newmenciptakan objek, sedangkan blok adalah bagian dari objek.
Dan ada perbedaan lain antara lambda dan Proc.new, yang merupakan penanganan argumen (salah) mereka. lambda mengeluh tentang itu, sementara Proc.newmengabaikan argumen tambahan atau menganggap tidak adanya argumen sebagai nol.
irb(main):021:0> l =->(x){ x.to_s }=>#<Proc:0x8b63750@(irb):21 (lambda)>
irb(main):022:0> p =Proc.new {|x| x.to_s}=>#<Proc:0x8b59494@(irb):22>
irb(main):025:0> l.call
ArgumentError: wrong number of arguments (0for1)
from (irb):21:in`block in irb_binding'
from (irb):25:in `call'
from (irb):25
from /usr/bin/irb:11:in `<main>'
irb(main):026:0> p.call
=>""
irb(main):049:0> l.call 1,2ArgumentError: wrong number of arguments (2for1)
from (irb):47:in`block in irb_binding'
from (irb):49:in `call'
from (irb):49
from /usr/bin/irb:11:in `<main>'
irb(main):050:0> p.call 1,2=>"1"
BTW, procdi Ruby 1.8 menciptakan lambda, sementara di Ruby 1.9+ berperilaku seperti Proc.new, yang benar-benar membingungkan.
Perhatikan bahwa Proc.newmembuat proc keluar dengan melewati blok. Saya percaya itu lambda {...}diurai sebagai semacam literal, bukan pemanggilan metode yang melewati blok. returning dari dalam blok yang dilampirkan ke pemanggilan metode akan kembali dari metode, bukan blok, dan Proc.newkasing adalah contoh dari ini yang dimainkan.
(Ini 1.8. Saya tidak tahu bagaimana ini diterjemahkan ke 1.9.)
Saya agak terlambat dalam hal ini, tetapi ada satu hal besar tetapi sedikit diketahui tentang Proc.newtidak disebutkan dalam komentar sama sekali. Seperti dengan dokumentasi :
Proc::newdapat dipanggil tanpa blok hanya dalam metode dengan blok terlampir, dalam hal ini blok tersebut dikonversi keProc objek.
Yang mengatakan, Proc.newmari untuk metode rantai menghasilkan:
def m1
yield'Finally!'if block_given?enddef m2
m1 &Proc.new
end
m2 {|e| puts e }#⇒ Finally!
Menarik, ia melakukan hal yang sama dengan mendeklarasikan &blockargumen dalam def, tetapi tanpa harus melakukannya dalam daftar argumen arg.
jrochkind
2
Perlu ditekankan bahwa returndalam proc, kembali dari metode lexically enclosure, yaitu metode di mana proc dibuat , bukan metode yang disebut proc. Ini adalah konsekuensi dari properti penutupan procs. Jadi kode berikut tidak menghasilkan apa-apa:
Meskipun proc mengeksekusi foobar, itu dibuat foodan returnkeluar foo, bukan hanya foobar. Seperti yang ditulis Charles Caldwell di atas, ia memiliki perasaan GOTO. Menurut pendapat saya, returnbaik-baik saja di blok yang dieksekusi dalam konteks leksikal, tetapi jauh kurang intuitif ketika digunakan dalam proc yang dieksekusi dalam konteks yang berbeda.
Untuk memperbarui: procs sekarang dapat dibuat menggunakan proc {}. Saya tidak yakin kapan ini mulai berlaku, tetapi (sedikit) lebih mudah daripada harus mengetikkan Proc.new.
Jawaban:
Perbedaan penting lainnya yang tidak kentara antara procs yang dibuat dengan
lambda
dan procs yang dibuatProc.new
adalah bagaimana mereka menanganireturn
pernyataan:lambda
proc yang dibuat,return
pernyataan hanya mengembalikan dari proc itu sendiriProc.new
proc yang dibuat,return
pernyataan itu sedikit lebih mengejutkan: ia mengembalikan kontrol tidak hanya dari proc, tetapi juga dari metode yang melampirkan proc!Inilah
lambda
-pro yang dibuatreturn
dalam aksi. Berperilaku dengan cara yang mungkin Anda harapkan:Sekarang inilah
Proc.new
proc yang dibuatreturn
melakukan hal yang sama. Anda akan melihat salah satu kasus di mana Ruby melanggar Prinsip Least Surprise yang banyak dibanggakan:Berkat perilaku ini mengejutkan (serta kurang mengetik), saya cenderung untuk mendukung menggunakan
lambda
lebihProc.new
ketika membuat procs.sumber
proc
metode. Apakah itu hanya singkatanProc.new
?proc
sama denganProc.new
proc
bertindak sukalambda
dan tidak sukaProc.new
sehubungan dengan pernyataan pengembalian. Itu berarti ruby doc tidak akurat.proc
bertindak sepertilambda
di 1.8, tetapi bertindak sepertiProc.new
di 1.9. Lihat jawaban Peter Wagenet.lambda
adalah metode anonim. Karena ini adalah metode, ia mengembalikan nilai, dan metode yang menyebutnya dapat melakukan apa pun yang diinginkannya, termasuk mengabaikannya dan mengembalikan nilai yang berbeda. AProc
seperti menempelkan dalam cuplikan kode. Itu tidak bertindak seperti metode. Jadi ketika pengembalian terjadi di dalamProc
, itu hanya bagian dari kode metode yang memanggilnya.Untuk memberikan klarifikasi lebih lanjut:
Joey mengatakan bahwa perilaku pengembalian
Proc.new
mengejutkan. Namun ketika Anda menganggap bahwa Proc.new berperilaku seperti blok, ini tidak mengherankan karena itulah persisnya perilaku blok. lambas di sisi lain berperilaku lebih seperti metode.Ini sebenarnya menjelaskan mengapa Procs fleksibel ketika datang ke arity (jumlah argumen) sedangkan lambda tidak. Blok tidak memerlukan semua argumen mereka diberikan tetapi metode melakukannya (kecuali jika standar disediakan). Meskipun memberikan argumen lambda default bukanlah pilihan di Ruby 1.8, sekarang didukung di Ruby 1.9 dengan sintaks alternatif lambda (seperti yang dicatat oleh webmat):
Dan Michiel de Mare (OP) salah tentang Procs dan lambda berperilaku sama dengan arity di Ruby 1.9. Saya telah memverifikasi bahwa mereka masih mempertahankan perilaku dari 1,8 seperti yang ditentukan di atas.
break
pernyataan sebenarnya tidak masuk akal baik dalam Procs atau lambdas. Dalam Procs, break akan mengembalikan Anda dari Proc.new yang telah selesai. Dan tidak masuk akal untuk melepaskan diri dari lambda karena pada dasarnya ini adalah metode, dan Anda tidak akan pernah melepaskan diri dari level teratas metode.next
,,redo
danraise
berperilaku sama dalam Procs dan lambdas. Padahalretry
tidak diperbolehkan di keduanya dan akan memunculkan eksepsi.Dan akhirnya,
proc
metode ini tidak boleh digunakan karena tidak konsisten dan memiliki perilaku yang tidak terduga. Di Ruby 1.8 sebenarnya mengembalikan lambda! Di Ruby 1.9 ini telah diperbaiki dan mengembalikan Proc. Jika Anda ingin membuat Proc, tetap denganProc.new
.Untuk informasi lebih lanjut, saya sangat merekomendasikan O'Reilly The Ruby Programming Language yang merupakan sumber saya untuk sebagian besar informasi ini.
sumber
break
dari Procs menimbulkanLocalJumpError
, sedangkanbreak
dari lambdas berperilaku sepertireturn
( yaitu ,return nil
).Saya menemukan halaman ini yang menunjukkan apa perbedaan antara
Proc.new
danlambda
. Menurut halaman, satu-satunya perbedaan adalah bahwa lambda ketat tentang jumlah argumen yang diterimanya, sedangkanProc.new
mengkonversi argumen yang hilang menjadinil
. Berikut adalah contoh sesi IRB yang menggambarkan perbedaan:Halaman ini juga merekomendasikan penggunaan lambda kecuali Anda secara spesifik menginginkan perilaku toleran kesalahan. Saya setuju dengan sentimen ini. Menggunakan lambda tampaknya sedikit lebih ringkas, dan dengan perbedaan yang tidak signifikan, tampaknya pilihan yang lebih baik dalam situasi rata-rata.
Adapun Ruby 1.9, maaf, saya belum melihat ke 1.9, tapi saya tidak membayangkan mereka akan banyak mengubahnya (jangan menuruti kata saya untuk itu, sepertinya Anda telah mendengar beberapa perubahan, jadi Saya mungkin salah di sana).
sumber
Proc lebih tua, tetapi semantik pengembalian sangat berlawanan dengan saya (setidaknya ketika saya belajar bahasa) karena:
Lambda secara fungsional lebih aman dan lebih mudah untuk dipikirkan - saya selalu menggunakannya daripada proc.
sumber
Saya tidak bisa bicara banyak tentang perbedaan yang halus. Namun, saya dapat menunjukkan bahwa Ruby 1.9 sekarang memungkinkan parameter opsional untuk lambdas dan blok.
Berikut sintaks baru untuk lambdas yang stabby di bawah 1.9:
Ruby 1.8 tidak memiliki sintaks itu. Cara konvensional mendeklarasikan block / lambdas juga tidak mendukung argumen opsional:
Namun, Ruby 1.9 mendukung argumen opsional bahkan dengan sintaks lama:
Jika Anda ingin membangun Ruby1.9 untuk Leopard atau Linux, lihat artikel ini (promosi mandiri yang tidak tahu malu).
sumber
Jawaban singkat: Yang penting adalah apa yang
return
dilakukan: lambda kembali dengan sendirinya, dan proc kembali dari dirinya sendiri DAN fungsi yang memanggilnya.Yang kurang jelas adalah mengapa Anda ingin menggunakan masing-masing. lambda adalah apa yang kita harapkan harus dilakukan dalam pengertian pemrograman fungsional. Ini pada dasarnya merupakan metode anonim dengan lingkup saat ini secara otomatis terikat. Dari keduanya, lambda adalah yang mungkin harus Anda gunakan.
Proc, di sisi lain, sangat berguna untuk mengimplementasikan bahasa itu sendiri. Misalnya, Anda dapat menerapkan pernyataan "jika" atau "untuk" loop dengannya. Setiap pengembalian yang ditemukan dalam proc akan kembali dari metode yang memanggilnya, bukan hanya pernyataan "jika". Beginilah cara kerja bahasa, bagaimana pernyataan "jika" bekerja, jadi tebakan saya adalah Ruby menggunakan ini di balik selimut dan mereka hanya mengeksposnya karena sepertinya kuat.
Anda hanya benar-benar membutuhkan ini jika Anda membuat konstruksi bahasa baru seperti loop, konstruksi if-else, dll.
sumber
Cara yang baik untuk melihatnya adalah bahwa lambda dieksekusi dalam ruang lingkup mereka sendiri (seolah-olah itu adalah pemanggilan metode), sementara Procs dapat dilihat sebagai dieksekusi sesuai dengan metode pemanggilan, setidaknya itu adalah cara yang baik untuk memutuskan mana yang akan digunakan dalam setiap kasus.
sumber
Saya tidak melihat ada komentar pada metode ketiga dalam pencarian, "proc" yang sudah usang, tetapi ditangani secara berbeda dalam 1,8 dan 1,9.
Berikut adalah contoh yang cukup bertele-tele yang membuatnya mudah untuk melihat perbedaan antara tiga panggilan serupa:
sumber
proc
mengembalikan lambda dalam 1,8; sekarang telah diperbaiki untuk mengembalikan proc di 1.9 - namun ini merupakan perubahan besar; karenanya tidak direkomendasikan untuk digunakan lagiPenutupan di Ruby adalah gambaran umum yang bagus untuk bagaimana blok, lambda dan proc bekerja di Ruby, dengan Ruby.
sumber
lambda berfungsi seperti yang diharapkan, seperti dalam bahasa lain.
Kabelnya
Proc.new
mengejutkan dan membingungkan.The
return
pernyataan dalam proc dibuat olehProc.new
tidak hanya akan mengembalikan kontrol hanya dari dirinya sendiri, tetapi juga dari metode melampirkan itu .Anda bisa membantah bahwa
Proc.new
memasukkan kode ke dalam metode melampirkan, seperti halnya blok. TetapiProc.new
menciptakan objek, sedangkan blok adalah bagian dari objek.Dan ada perbedaan lain antara lambda dan
Proc.new
, yang merupakan penanganan argumen (salah) mereka. lambda mengeluh tentang itu, sementaraProc.new
mengabaikan argumen tambahan atau menganggap tidak adanya argumen sebagai nol.BTW,
proc
di Ruby 1.8 menciptakan lambda, sementara di Ruby 1.9+ berperilaku sepertiProc.new
, yang benar-benar membingungkan.sumber
Untuk menguraikan respons Accordion Guy:
Perhatikan bahwa
Proc.new
membuat proc keluar dengan melewati blok. Saya percaya itulambda {...}
diurai sebagai semacam literal, bukan pemanggilan metode yang melewati blok.return
ing dari dalam blok yang dilampirkan ke pemanggilan metode akan kembali dari metode, bukan blok, danProc.new
kasing adalah contoh dari ini yang dimainkan.(Ini 1.8. Saya tidak tahu bagaimana ini diterjemahkan ke 1.9.)
sumber
Saya agak terlambat dalam hal ini, tetapi ada satu hal besar tetapi sedikit diketahui tentang
Proc.new
tidak disebutkan dalam komentar sama sekali. Seperti dengan dokumentasi :Yang mengatakan,
Proc.new
mari untuk metode rantai menghasilkan:sumber
&block
argumen dalamdef
, tetapi tanpa harus melakukannya dalam daftar argumen arg.Perlu ditekankan bahwa
return
dalam proc, kembali dari metode lexically enclosure, yaitu metode di mana proc dibuat , bukan metode yang disebut proc. Ini adalah konsekuensi dari properti penutupan procs. Jadi kode berikut tidak menghasilkan apa-apa:Meskipun proc mengeksekusi
foobar
, itu dibuatfoo
danreturn
keluarfoo
, bukan hanyafoobar
. Seperti yang ditulis Charles Caldwell di atas, ia memiliki perasaan GOTO. Menurut pendapat saya,return
baik-baik saja di blok yang dieksekusi dalam konteks leksikal, tetapi jauh kurang intuitif ketika digunakan dalam proc yang dieksekusi dalam konteks yang berbeda.sumber
Perbedaan perilaku dengan
return
IMHO perbedaan paling penting antara 2. Saya juga lebih suka lambda karena kurang mengetik daripada Proc.new :-)sumber
proc {}
. Saya tidak yakin kapan ini mulai berlaku, tetapi (sedikit) lebih mudah daripada harus mengetikkan Proc.new.