Salah satu perbedaan adalah cara mereka menangani argumen. Membuat proc menggunakan proc {}dan Proc.new {}setara. Namun, menggunakan lambda {}memberi Anda proc yang memeriksa jumlah argumen yang diteruskan ke sana. Dari ri Kernel#lambda:
Setara dengan Proc.new , kecuali objek Proc yang dihasilkan memeriksa jumlah parameter yang dilewati saat dipanggil.
Sebuah contoh:
p =Proc.new {|a, b| puts a**2+b**2}# => #<Proc:0x3c7d28@(irb):1>
p.call 1,2# => 5
p.call 1# => NoMethodError: undefined method `**' for nil:NilClass
p.call 1,2,3# => 5
l = lambda {|a, b| puts a**2+b**2}# => #<Proc:0x15016c@(irb):5 (lambda)>
l.call 1,2# => 5
l.call 1# => ArgumentError: wrong number of arguments (1 for 2)
l.call 1,2,3# => ArgumentError: wrong number of arguments (3 for 2)
Selain itu, seperti yang ditunjukkan Ken, menggunakan returndi dalam lambda mengembalikan nilai lambda itu, tetapi menggunakan returndalam proc kembali dari blok penutup.
Jadi untuk sebagian besar penggunaan cepat, keduanya sama, tetapi jika Anda ingin memeriksa argumen ketat secara otomatis (yang kadang-kadang juga dapat membantu dengan debugging), atau jika Anda perlu menggunakan returnpernyataan untuk mengembalikan nilai dari proc, gunakan lambda.
Apakah akurat untuk mengatakan bahwa lambda sangat mirip metode (periksa argumen dan pengembalian akan kembali dari mereka) sementara procs sangat mirip blok (argumen tidak dicentang dan pengembalian akan kembali dari metode yang mengandung atau lambda)?
pedz
Saya telah ke Tuhan tahu berapa banyak situs web dan artikel sekarang dan tampaknya tidak ada yang berbicara tentang kegunaan Procs vs metode vs lambdas. Setiap penjelasan hanya memberikan perincian yang memecah-belah tentang bagaimana nilai-nilai pengembalian, dll. Berbeda, tetapi tidak ada mengapa itu penting. Untuk saat ini saya harus menyimpulkan bahwa ini adalah kekacauan desain di Ruby.
ankush981
76
Perbedaan nyata antara procs dan lambdas ada hubungannya dengan kontrol kata kunci aliran. Saya berbicara tentang return, raise, break, redo, retrydll - kata-kata kontrol. Katakanlah Anda memiliki pernyataan pengembalian dalam sebuah proc. Ketika Anda memanggil proc Anda, itu tidak hanya akan membuang Anda keluar dari itu, tetapi juga akan kembali dari metode terlampir misalnya:
Final putsdalam metode, tidak pernah dieksekusi, karena ketika kami memanggil proc kami, bagian returndalamnya membuang kami keluar dari metode. Namun, jika kami mengubah proc kami menjadi lambda, kami mendapatkan yang berikut:
def my_method
puts "before proc"
my_proc = lambda do
puts "inside proc"returnend
my_proc.call
puts "after proc"end
my_method
shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
after proc
Pengembalian dalam lambda hanya membuang kita keluar dari lambda itu sendiri dan metode terlampir terus dijalankan. Cara kontrol aliran kata kunci diperlakukan dalam procs dan lambdas adalah perbedaan utama di antara mereka
Pertama, a lambdamemeriksa jumlah argumen yang diteruskan ke sana, sementara a proctidak. Ini berarti bahwa a lambdaakan melempar kesalahan jika Anda memberikannya jumlah argumen yang salah, sedangkan a procakan mengabaikan argumen yang tidak terduga dan menugaskan nilsiapa pun yang hilang.
Kedua, ketika lambdakembali, ia melewati kontrol kembali ke metode pemanggilan; ketika prockembali, ia melakukannya segera, tanpa kembali ke metode panggilan.
Untuk melihat cara kerjanya, lihat kode di bawah ini. Metode pertama kami memanggil a proc; panggilan kedua a lambda.
def batman_ironman_proc
victor =Proc.new {return"Batman will win!"}
victor.call
"Iron Man will win!"end
puts batman_ironman_proc # prints "Batman will win!"def batman_ironman_lambda
victor = lambda {return"Batman will win!"}
victor.call
"Iron Man will win!"end
puts batman_ironman_lambda # prints "Iron Man will win!"
Lihat bagaimana prockata "Batman akan menang!", Ini karena ia segera kembali, tanpa kembali ke metode batman_ironman_proc.
Kami lambda, bagaimanapun, kembali ke metode setelah dipanggil, sehingga metode mengembalikan kode terakhir mengevaluasi: "! Iron Man akan menang"
1. Lambdas memeriksa jumlah argumen, sementara procs tidak
lam = lambda {|x| puts x }# creates a lambda that takes 1 argument
lam.call(2)# prints out 2
lam.call # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3)# ArgumentError: wrong number of arguments (3 for 1)
Sebaliknya, procs tidak peduli jika mereka melewati jumlah argumen yang salah.
proc =Proc.new {|x| puts x }# creates a proc that takes 1 argument
proc.call(2)# prints out 2
proc.call # returns nil
proc.call(1,2,3)# prints out 1 and forgets about the extra arguments
2. Lambdas dan procs memperlakukan kata kunci 'kembali' secara berbeda
'kembali' di dalam lambda memicu kode tepat di luar kode lambda
Dan untuk menjawab pertanyaan Anda yang lain, mana yang harus digunakan dan kapan? Saya akan mengikuti @jtbandes seperti yang dia sebutkan
Jadi untuk sebagian besar penggunaan cepat, keduanya sama, tetapi jika Anda ingin memeriksa argumen ketat secara otomatis (yang terkadang juga dapat membantu debugging), atau jika Anda perlu menggunakan pernyataan pengembalian untuk mengembalikan nilai dari proc, gunakan lambda.
Secara umum, lambda lebih intuitif daripada procs karena mereka lebih mirip dengan metode. Mereka cukup ketat tentang arity, dan mereka hanya keluar ketika Anda menelepon kembali. Untuk alasan ini, banyak Rubyists menggunakan lambdas sebagai pilihan pertama, kecuali mereka membutuhkan fitur khusus procs.
Procs: Objek kelas Proc. Seperti blok, mereka dievaluasi dalam lingkup di mana mereka didefinisikan.
Lambdas: Juga objek kelas Proctetapi sedikit berbeda dari procs biasa. Mereka penutupan seperti blok dan procs, dan dengan demikian mereka dievaluasi dalam lingkup di mana mereka didefinisikan.
a = proc { |x| x 2 }sama dengana = Proc.new { |x| x 2 }
lacostenycoder
1
Berikut ini cara lain untuk memahami hal ini.
Blok adalah bongkahan kode yang dilampirkan pada pemanggilan panggilan metode pada suatu objek. Dalam contoh di bawah ini, self adalah turunan dari kelas anonim yang mewarisi dari ActionView :: Base dalam kerangka Rails (yang itu sendiri mencakup banyak modul pembantu). kartu adalah metode yang kita sebut sendiri. Kami menyampaikan argumen ke metode dan kemudian kami selalu melampirkan blok ke akhir doa metode:
self.card :contacts do|c|// a chunk of valid ruby code
end
Oke, jadi kami mengirimkan sepotong kode ke sebuah metode. Tetapi bagaimana kita memanfaatkan blok ini? Salah satu opsi adalah mengubah potongan kode menjadi objek. Ruby menawarkan tiga cara untuk mengubah sepotong kode menjadi objek
# lambda> l = lambda {|a| a +1}> l.call(1)=>2# Proc.new> l2=Proc.new {|a| a +1}> l2.call(1)=>2# & as the last method argument with a local variable namedef add(&block)end
Dalam metode di atas, & mengubah blok yang diteruskan ke metode menjadi objek dan menyimpan objek itu di blok variabel lokal. Bahkan, kami dapat menunjukkan bahwa ia memiliki perilaku yang sama dengan lambda dan Proc.new:
def add(&block)
block
end
l3 = add {|a| a +1}
l3.call(1)=>2
Ini penting. Saat Anda meneruskan blok ke metode dan mengonversinya menggunakan &, objek yang dibuatnya menggunakan Proc.new untuk melakukan konversi.
Perhatikan bahwa saya menghindari penggunaan "proc" sebagai opsi. Itu karena Ruby 1.8, sama dengan lambda dan di Ruby 1.9, itu sama dengan Proc.new dan di semua versi Ruby itu harus dihindari.
Jadi, Anda bertanya apa perbedaan antara lambda dan Proc.new?
Pertama, dalam hal melewati parameter, lambda berperilaku seperti pemanggilan metode. Ini akan memunculkan pengecualian jika Anda melewatkan jumlah argumen yang salah. Sebaliknya, Proc.new berperilaku seperti penugasan paralel. Semua argumen yang tidak digunakan dikonversi menjadi nihil:
> l = lambda {|a,b| puts "#{a} + #{b}"}=>#<Proc:0x007fbffcb47e40@(irb):19 (lambda)> > l.call(1)ArgumentError: wrong number of arguments (1for2)> l2 =Proc.new {|a,b| puts "#{a} + #{b}"}=>#<Proc:0x007fbffcb261a0@(irb):21> > l2.call(1)1+
Kedua, lambda dan Proc.new menangani kata kunci kembali secara berbeda. Ketika Anda melakukan pengembalian di dalam Proc.new, itu sebenarnya kembali dari metode melampirkan, yaitu konteks sekitarnya. Ketika Anda kembali dari blok lambda, itu hanya kembali dari blok, bukan metode melampirkan. Pada dasarnya, ia keluar dari panggilan ke blok dan melanjutkan eksekusi dengan sisa metode terlampir.
>def add(a,b)
l =Proc.new {return a + b}
l.call
puts "now exiting method"end> add(1,1)=>2# NOTICE it never prints the message "now exiting method">def add(a,b)
l = lambda {return a + b }
l.call
puts "now exiting method"end> add(1,1)=> now exiting method # NOTICE this time it prints the message "now exiting method"
Lantas mengapa perbedaan perilaku ini? Alasannya adalah karena dengan Proc.new baru, kita dapat menggunakan iterator dalam konteks melampirkan metode dan menarik kesimpulan logis. Lihatlah contoh ini:
>def print(max)[1,2,3,4,5].each do|val|
puts val
returnif val > max
endend> print(3)1234
Kami berharap bahwa ketika kami meminta return di dalam iterator, itu akan kembali dari metode terlampir. Ingat blok yang dilewatkan ke iterator dapat dikonversi ke objek menggunakan Proc.new dan itulah sebabnya ketika kita menggunakan return, itu akan keluar dari metode melampirkan.
Anda dapat menganggap lambdas sebagai metode anonim, mereka mengisolasi blok kode individu menjadi objek yang dapat diperlakukan seperti metode. Pada akhirnya, pikirkan lambda sebagai berperilaku sebagai metode anomi dan Proc.new baru berperilaku sebagai kode inline.
perbedaan antara proc dan lambda adalah proc hanya salinan kode dengan argumen diganti pada gilirannya, sedangkan lambda adalah fungsi seperti dalam bahasa lain. (perilaku pengembalian, pemeriksaan argumen)
return
pernyataan kembaliproc
dibandingkan denganlambda
.Jawaban:
Salah satu perbedaan adalah cara mereka menangani argumen. Membuat proc menggunakan
proc {}
danProc.new {}
setara. Namun, menggunakanlambda {}
memberi Anda proc yang memeriksa jumlah argumen yang diteruskan ke sana. Dariri Kernel#lambda
:Sebuah contoh:
Selain itu, seperti yang ditunjukkan Ken, menggunakan
return
di dalam lambda mengembalikan nilai lambda itu, tetapi menggunakanreturn
dalam proc kembali dari blok penutup.Jadi untuk sebagian besar penggunaan cepat, keduanya sama, tetapi jika Anda ingin memeriksa argumen ketat secara otomatis (yang kadang-kadang juga dapat membantu dengan debugging), atau jika Anda perlu menggunakan
return
pernyataan untuk mengembalikan nilai dari proc, gunakanlambda
.sumber
Perbedaan nyata antara procs dan lambdas ada hubungannya dengan kontrol kata kunci aliran. Saya berbicara tentang
return
,raise
,break
,redo
,retry
dll - kata-kata kontrol. Katakanlah Anda memiliki pernyataan pengembalian dalam sebuah proc. Ketika Anda memanggil proc Anda, itu tidak hanya akan membuang Anda keluar dari itu, tetapi juga akan kembali dari metode terlampir misalnya:Final
puts
dalam metode, tidak pernah dieksekusi, karena ketika kami memanggil proc kami, bagianreturn
dalamnya membuang kami keluar dari metode. Namun, jika kami mengubah proc kami menjadi lambda, kami mendapatkan yang berikut:Pengembalian dalam lambda hanya membuang kita keluar dari lambda itu sendiri dan metode terlampir terus dijalankan. Cara kontrol aliran kata kunci diperlakukan dalam procs dan lambdas adalah perbedaan utama di antara mereka
sumber
Hanya ada dua perbedaan utama.
lambda
memeriksa jumlah argumen yang diteruskan ke sana, sementara aproc
tidak. Ini berarti bahwa alambda
akan melempar kesalahan jika Anda memberikannya jumlah argumen yang salah, sedangkan aproc
akan mengabaikan argumen yang tidak terduga dan menugaskannil
siapa pun yang hilang.lambda
kembali, ia melewati kontrol kembali ke metode pemanggilan; ketikaproc
kembali, ia melakukannya segera, tanpa kembali ke metode panggilan.Untuk melihat cara kerjanya, lihat kode di bawah ini. Metode pertama kami memanggil a
proc
; panggilan kedua alambda
.Lihat bagaimana
proc
kata "Batman akan menang!", Ini karena ia segera kembali, tanpa kembali ke metode batman_ironman_proc.Kami
lambda
, bagaimanapun, kembali ke metode setelah dipanggil, sehingga metode mengembalikan kode terakhir mengevaluasi: "! Iron Man akan menang"sumber
# Contoh Proc
# Contoh Lambda
Perbedaan antara Procs dan Lambdas
Sebelum saya membahas perbedaan antara procs dan lambdas, penting untuk menyebutkan bahwa keduanya adalah objek Proc.
Namun, lambda adalah 'rasa' procs yang berbeda. Perbedaan kecil ini ditunjukkan ketika mengembalikan objek.
1. Lambdas memeriksa jumlah argumen, sementara procs tidak
Sebaliknya, procs tidak peduli jika mereka melewati jumlah argumen yang salah.
2. Lambdas dan procs memperlakukan kata kunci 'kembali' secara berbeda
'kembali' di dalam lambda memicu kode tepat di luar kode lambda
'kembali' di dalam proc memicu kode di luar metode di mana proc dieksekusi
Dan untuk menjawab pertanyaan Anda yang lain, mana yang harus digunakan dan kapan? Saya akan mengikuti @jtbandes seperti yang dia sebutkan
Awalnya diposting di sini
sumber
Secara umum, lambda lebih intuitif daripada procs karena mereka lebih mirip dengan metode. Mereka cukup ketat tentang arity, dan mereka hanya keluar ketika Anda menelepon kembali. Untuk alasan ini, banyak Rubyists menggunakan lambdas sebagai pilihan pertama, kecuali mereka membutuhkan fitur khusus procs.
Procs: Objek kelas
Proc
. Seperti blok, mereka dievaluasi dalam lingkup di mana mereka didefinisikan. Lambdas: Juga objek kelasProc
tetapi sedikit berbeda dari procs biasa. Mereka penutupan seperti blok dan procs, dan dengan demikian mereka dievaluasi dalam lingkup di mana mereka didefinisikan.Membuat Proc
Menciptakan lambda
b = lambda { |x| x 2
}sumber
a = proc { |x| x 2 }
sama dengana = Proc.new { |x| x 2 }
Berikut ini cara lain untuk memahami hal ini.
Blok adalah bongkahan kode yang dilampirkan pada pemanggilan panggilan metode pada suatu objek. Dalam contoh di bawah ini, self adalah turunan dari kelas anonim yang mewarisi dari ActionView :: Base dalam kerangka Rails (yang itu sendiri mencakup banyak modul pembantu). kartu adalah metode yang kita sebut sendiri. Kami menyampaikan argumen ke metode dan kemudian kami selalu melampirkan blok ke akhir doa metode:
Oke, jadi kami mengirimkan sepotong kode ke sebuah metode. Tetapi bagaimana kita memanfaatkan blok ini? Salah satu opsi adalah mengubah potongan kode menjadi objek. Ruby menawarkan tiga cara untuk mengubah sepotong kode menjadi objek
Dalam metode di atas, & mengubah blok yang diteruskan ke metode menjadi objek dan menyimpan objek itu di blok variabel lokal. Bahkan, kami dapat menunjukkan bahwa ia memiliki perilaku yang sama dengan lambda dan Proc.new:
Ini penting. Saat Anda meneruskan blok ke metode dan mengonversinya menggunakan &, objek yang dibuatnya menggunakan Proc.new untuk melakukan konversi.
Perhatikan bahwa saya menghindari penggunaan "proc" sebagai opsi. Itu karena Ruby 1.8, sama dengan lambda dan di Ruby 1.9, itu sama dengan Proc.new dan di semua versi Ruby itu harus dihindari.
Jadi, Anda bertanya apa perbedaan antara lambda dan Proc.new?
Pertama, dalam hal melewati parameter, lambda berperilaku seperti pemanggilan metode. Ini akan memunculkan pengecualian jika Anda melewatkan jumlah argumen yang salah. Sebaliknya, Proc.new berperilaku seperti penugasan paralel. Semua argumen yang tidak digunakan dikonversi menjadi nihil:
Kedua, lambda dan Proc.new menangani kata kunci kembali secara berbeda. Ketika Anda melakukan pengembalian di dalam Proc.new, itu sebenarnya kembali dari metode melampirkan, yaitu konteks sekitarnya. Ketika Anda kembali dari blok lambda, itu hanya kembali dari blok, bukan metode melampirkan. Pada dasarnya, ia keluar dari panggilan ke blok dan melanjutkan eksekusi dengan sisa metode terlampir.
Lantas mengapa perbedaan perilaku ini? Alasannya adalah karena dengan Proc.new baru, kita dapat menggunakan iterator dalam konteks melampirkan metode dan menarik kesimpulan logis. Lihatlah contoh ini:
Kami berharap bahwa ketika kami meminta return di dalam iterator, itu akan kembali dari metode terlampir. Ingat blok yang dilewatkan ke iterator dapat dikonversi ke objek menggunakan Proc.new dan itulah sebabnya ketika kita menggunakan return, itu akan keluar dari metode melampirkan.
Anda dapat menganggap lambdas sebagai metode anonim, mereka mengisolasi blok kode individu menjadi objek yang dapat diperlakukan seperti metode. Pada akhirnya, pikirkan lambda sebagai berperilaku sebagai metode anomi dan Proc.new baru berperilaku sebagai kode inline.
sumber
Pos bermanfaat tentang panduan ruby: blok, procs & lambdas
sumber
perbedaan antara proc dan lambda adalah proc hanya salinan kode dengan argumen diganti pada gilirannya, sedangkan lambda adalah fungsi seperti dalam bahasa lain. (perilaku pengembalian, pemeriksaan argumen)
sumber