lambda ne zaman kullanılır, ne zaman Proc.new kullanılır?

oy
316

Ruby 1.8 olarak, ince bir yandan proc / lambda arasındaki farklar, ve orada Proc.newdiğer tarafta.

  • Bu farklar nelerdir?
  • Eğer seçim için karar vermek konusunda yönergeler verebilir misiniz?
  • Ruby 1.9 içinde, Proc ve lambda farklıdır. Anlaşma ne?
Oluştur 03/08/2008 saat 07:40
kaynak kullanıcı
Diğer dillerde...                            


15 cevaplar

oy
364

Ile oluşturulan procs arasındaki bir diğer önemli ancak ince bir fark lambdaile oluşturulan ve procs Proc.newbaktıkları nasıl returndeyimi:

  • Bir de lambda-created proc, returndeyim sadece proc kendisinden döner
  • Bir de Proc.new-created proc, returndeyim biraz daha şaşırtıcıdır: bu sadece proc değil kontrolünü verir, ama aynı zamanda proc çevreleyen yönteminden!

İşte lambdaproc en -created returneylem. Bu muhtemelen bekliyoruz şekilde davranır:

def whowouldwin

  mylambda = lambda {return "Freddy"}
  mylambda.call

  # mylambda gets called and returns "Freddy", and execution
  # continues on the next line

  return "Jason"

end


whowouldwin
#=> "Jason"

Şimdi burada var Proc.new-created proc en returnaynı şeyi yapıyor. Ruby Az Surprise çok vaunted İlke kırar vakalardan biri görmek üzeresiniz:

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"

Bu şaşırtıcı davranış (yanı sıra daha az yazarak) sayesinde kullanıyorum lehine eğilimindedir lambdaüzerinde Proc.newprocs yaparken.

Cevap 03/08/2008 saat 16:21
kaynak kullanıcı

oy
93

daha fazla açıklama sağlamak için:

Joey dönüşü davranışı söylüyor Proc.newşaşırtıcıdır. Ancak Proc.new bu tam olarak bloke nasıl davrandığını olduğu gibi şaşırtıcı değildir blok gibi davranır göz önüne aldığımızda. Öte yandan lambas daha yöntemlerle gibi davranırlar.

Yordamlara esnektir neden lambda'lar değildir oysa o Arity (bağımsız değişkenlerin sayısı) geldiğinde bu aslında açıklıyor. Bloklar tüm argümanlar sağlanan ancak (varsayılan sağlanmadıkça) yöntemleri yapmak üzere gerektirmez. lambda argüman varsayılan sağlayan Ruby 1.8 bir seçenek olmasa da (webmat tarafından belirtildiği gibi), artık alternatif lambda sözdizimi Ruby 1.9 desteklenir:

concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1)   # => "12"

Ve Michiel de Mare (OP) Ruby 1.9 Arity ile aynı davranıyor Yordamlara ve lambda ilgili yanlıştır. Yukarıda belirtildiği gibi onlar hala 1.8 ila davranışı sürdürmek doğruladıktan.

breakifadeleri aslında Yordamlara veya lambdas ya çok mantıklı değil. Procs, kırılma zaten tamamlandı Proc.new sizi dönecekti. Ve bunun aslında bir yöntem olduğundan herhangi duyum bir lambda kırmaya yapmaz ve bir yöntemin üst düzeyden kırmak asla.

next, redoVe raiseprocs ve lambdas hem de aynı davranırlar. Oysa retrybirinde izin verilmez ve bir istisna yükseltecektir.

Ve nihayet, procbu tutarsız ve beklenmeyen davranışlar sahip olduğu yöntem asla kullanılmamalıdır. Ruby 1.8 olarak aslında bir lambda döndürür! Ruby 1.9 bu giderildi ve bir Proc döndürür. Bir Proc oluşturmak istiyorsanız, sopa ile Proc.new.

Daha fazla bilgi için, ben çok O'Reilly'nin tavsiye Yakut Programlama Dili bu bilgilerin çoğunu benim kaynağıdır.

Cevap 04/10/2009 saat 06:23
kaynak kullanıcı

oy
41

Bulduğum bu sayfayı ne fark arasındaki gösterir Proc.newve lambdavardır. Sayfanın göre, tek fark ise bir lambda, bu kabul argümanlar sayısı hakkında kesin olmasıdır Proc.newdönüştürür argümanlar eksik nil. İşte fark gösteren bir örnek IRB oturumdur:

IRB (ana): 001: 0> l = lambda {| x, y | x + y}
=> # <Proc: 0x00007fc605ec0748 @ (IRB): 1>
IRB (ana): 002: 0> N = Proc.new {| x, y | x + y}
=> # <Proc: 0x00007fc605ea8698 @ (IRB): 2>
irb (ana): 003: 0> l.call "Merhaba", "dünya"
=> "Helloworld"
irb (ana): 004: 0> p.call "Merhaba", "dünya"
=> "Helloworld"
irb (ana): 005: 0> l.call "Merhaba"
ArgumentError: hatalı sayıda argüman (2 kişilik 1)
    den (IRB): 1
    5: çağrı 'in' (IRB) dan
    den (IRB): 5
    den 0
irb (ana): 006: 0> p.call "Merhaba"
TypeError: Dizesi'ne nil dönüştüremiyorsa
    den (IRB): 2: in '+'
    den (IRB): 2
    6: çağrı 'in' (IRB) dan
    den (IRB): 6
    den 0

sayfası da özel olarak hata toleranslı davranış istemedikçe lambda kullanılmasını önerir. Bu açıklamalarla hemfikir. Bir lambda kullanarak biraz daha özlü görünüyor ve böyle önemsiz bir fark ile, ortalama durumda daha iyi bir seçim gibi görünüyor.

Ruby 1.9 gelince, üzgünüm, ben henüz 1,9 bakmadım ama çok onlar o kadar (gerçi bunun için söz yapmayız, bazı değişikliklerin duymuş görünüyor hepsini değiştirecek hayal etme I) orada muhtemelen yanılıyorum.

Cevap 03/08/2008 saat 08:28
kaynak kullanıcı

oy
14

Proc eskidir, ama dönüş semantik (en azından ben dili öğrenme zaman) çünkü bana son derece gariptir şunlardır:

  1. Eğer proc kullanıyorsanız, büyük olasılıkla işlevsel paradigma çeşit kullanıyor.
  2. Proc temel olarak git ve doğada oldukça işlevsel olmayan kapatma alanı (önceki yanıtları bakınız) üzerinden dönebilir.

Lambda işlevsel güvenli ve hakkında akıl yürütme daha kolaydır - Hep proc yerine kullanabilirsiniz.

Cevap 11/09/2008 saat 00:32
kaynak kullanıcı

oy
11

Ben ince farklar hakkında pek söyleyemeyiz. Ancak, ben Ruby 1.9 şimdi lambdas ve bloklar için isteğe bağlı parametreleri verir işaret edebilir.

İşte 1.9 altında stabby lambdas için yeni sözdizimi var:

stabby = ->(msg='inside the stabby lambda') { puts msg }

Yakut 1.8 o sözdizimi yoktu. Ne blokları ilan geleneksel yollarla anlatan / lambda'lar opsiyonel args destekler:

# 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 }

Yakut 1.9 Ancak hatta eski sözdizimi ile isteğe bağlı argümanlar destekler:

l = lambda { |msg = 'inside the regular lambda'|  puts msg }
#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez

Eğer Leopard veya Linux için Ruby1.9 inşa etmek istiyorsan, kontrol bu makaleyi (utanmaz bir öz tanıtım).

Cevap 19/11/2008 saat 22:28
kaynak kullanıcı

oy
10

Kısa cevap: Önemli olan budur returnlamda kendisinin dışarı döner, kendi üzerinden proc getirilerini VE denir işlevi: yok.

Her neden kullanmak istediğinizi ne kadar net olmasıdır. lambda şeylerin fonksiyonel programlama anlamında yapmalıyım ne beklemek değildir. Temelde otomatik bağlanmış geçerli kapsamı ile anonim bir yöntemdir. iki ki, lambda muhtemelen kullanıyor olmalıdır biridir.

Proc, diğer taraftan, dili kendisi uygulanması için gerçekten yararlıdır. Örneğin onlarla döngüler "için" "eğer" ifadeleri veya uygulayabilir. proc bulunan herhangi dönüş sadece "eğer" ifadesi, bunu denilen yöntemle dışarı dönecektir. Bu ifadeler çalışmak "eğer", yani benim tahminim Yakut yorganın altında bu kullanır ve güçlü görünüyordu çünkü onlar sadece maruz nasıl, diller çalışmak nasıl.

Eğer döngüler gibi yeni dil yapıları oluştururken, yalnızca gerçekten if-else yapılara vb bu gerekir

Cevap 06/10/2011 saat 19:33
kaynak kullanıcı

oy
9

çağıran yöntemiyle satır içi infaz olarak yordamlara görülebilir iken onu görmek için iyi bir yolu, (bir yöntem çağrısı sanki) lambda'lar kendi kapsamında yürütülür yani en azından kullanmak wich birini karar iyi bir yoldur herbir durumda.

Cevap 09/12/2008 saat 15:17
kaynak kullanıcı

oy
8

Ben queston kullanımdan kaldırıldı, ancak 1.8 ve 1.9 farklı şekilde ele alınır, "proc" üçüncü yöntem üzerinde herhangi bir yorum fark etmedi.

İşte kolay üç benzer çağrılar arasındaki farkları görmek için yapar oldukça ayrıntılı bir örnek:

def meth1
  puts "method start"

  pr = lambda { return }
  pr.call

  puts "method end"  
end

def meth2
  puts "method start"

  pr = Proc.new { return }
  pr.call

  puts "method end"  
end

def meth3
  puts "method start"

  pr = proc { return }
  pr.call

  puts "method end"  
end

puts "Using lambda"
meth1
puts "--------"
puts "using Proc.new"
meth2
puts "--------"
puts "using proc"
meth3
Cevap 25/06/2009 saat 12:22
kaynak kullanıcı

oy
7

Ruby te kapanması için iyi bir bakıştır nasıl blokları, lambda ve Ruby ile Ruby proc eser.

Cevap 28/08/2008 saat 14:50
kaynak kullanıcı

oy
6

Yakut Blokları, procs ve Lambda'lar anlama Robert Sosinski tarafından açıkça bu programlama kavramları açıklar ve örnek kodu ile açıklamalar pekiştirir. Yöntem nesneleri ile ilgili ve de sahiptir.

Cevap 23/08/2013 saat 18:07
kaynak kullanıcı

oy
5

beklendiği gibi lambda dillerde olduğu gibi çalışır.

Kablolu Proc.newşaşırtıcı ve kafa karıştırıcı.

returnYarattığı proc deyimi Proc.newsadece ama sadece kendisinden kontrolünü döndürmez onu çevreleyen zamanda yönteminden .

def some_method
  myproc = Proc.new {return "End."}
  myproc.call

  # Any code below will not get executed!
  # ...
end

Bunu iddia edebilir Proc.newsadece bloğu gibi, kapsayan yöntem haline kodunu ekler. Ama Proc.newblok ise, bir nesneyi yaratır parçası bir nesne.

Ve lambda arasında bir fark vardır Proc.new(yanlış) Değişken bunların kullanımı olup,. ise, lambda, bunu şikayet Proc.newilave bağımsız değişkenler dikkate almaz ya da sıfır olarak bağımsız değişken olmadığını kabul etmektedir.

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 (0 for 1)
        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, 2
ArgumentError: wrong number of arguments (2 for 1)
        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, procYakut 1.9+ gibi davranır ise Ruby 1.8 içinde, bir lambda yaratır Proc.newgerçekten kafa karıştırıcı olan.

Cevap 29/10/2014 saat 16:22
kaynak kullanıcı

oy
3

Akordeon Guy tepkisi üzerinde durmak için:

Bildirim Proc.newbir proc dışarı yaratan bir blok geçirilen. O inanıyoruz lambda {...}hazır bir çeşit yerine bir blok geçen bir metod çağırma olarak ayrıştırılır. returnBir yöntem çağrısı bağlı bir blok içinden ing yöntemiyle değil, blok dönmek ve olacak Proc.newdurum oynayan bu bir örnektir.

(Bu 1.8 olduğunu. Bu 1,9 çevirir nasıl bilmiyorum.)

Cevap 07/09/2008 saat 03:31
kaynak kullanıcı

oy
2

Ben biraz geç bu konuda, ama yaklaşık bir harika ama biraz bilinen şey yoktur Proc.newhiç yorumların bahsedilmeyen. Tarafından gibi belgeler :

Proc::newSadece bu durumda bağlı bir blok, bir yöntem içinde, bir blok olmadan erişebilir blok dönüştürülürProc nesne.

Yani, söz konusu Proc.newzincir veren yöntemlere olanak tanır:

def m1
  yield 'Finally!' if block_given?
end

def m2
  m1 &Proc.new
end

m2 { |e| puts e } 
#⇒ Finally!
Cevap 28/04/2015 saat 13:15
kaynak kullanıcı

oy
1

O vurgulayan değer returnyani lexically çevreleyen yönteminden bir proc dönüşlerinde proc oluşturulduğu yönteme , değil proc denilen yöntem. Bu procs kapatma özelliğinin bir sonucudur. Yani aşağıdaki kod şey çıkarır:

def foo
  proc = Proc.new{return}
  foobar(proc)
  puts 'foo'
end

def foobar(proc)
  proc.call
  puts 'foobar'
end

foo

Proc içinde yürütür rağmen foobar, bu oluşturulmuş foove böylece returnçıkışlar foo, sadece foobar. Charles Caldwell Yukarıda yazdığı gibi, bir GOTO hissediyorum vardır. Bence, returnonun sözcük bağlamında yürütülen bir blokta iyi, ama farklı bir bağlamda yürütülen bir yordam kullanıldığında çok daha az sezgiseldir.

Cevap 15/11/2018 saat 10:00
kaynak kullanıcı

oy
1

Ile davranış farkı return:-) o Proc.new daha az yazarak çünkü 2. arasındaki en önemli fark, ben de lambda tercih IMHO olduğunu

Cevap 11/08/2008 saat 03:09
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more