Mikor kell használni lambda, hogy mikor kell használni Proc.new?

szavazat
316

A Ruby 1.8, vannak finom különbségek proc / lambda egyrészt, és Proc.newa másik oldalon.

  • Mik ezek a különbségek?
  • Tudna tudnivalóval eldönteni, melyiket válassza?
  • A Ruby 1.9, proc és lambda különböző. Mi a helyzet?
A kérdést 03/08/2008 07:40
a forrás felhasználó
Más nyelveken...                            


15 válasz

szavazat
41

Találtam ezt az oldalt , amely megmutatja, hogy mi a különbség Proc.new, és lambdavannak. Az oldal, az egyetlen különbség az, hogy a lambda szigorúak száma érvek elfogadja, mivel Proc.newáttértek hiányzó érveket nil. Itt egy példa IRB ülésen bemutatják a különbséget:

IRB (fő): 001: 0> L = lambda {| x, y | x + y}
=> # <Proc: 0x00007fc605ec0748 @ (IRB): 1>
IRB (fő): 002: 0> p = Proc.new {| x, y | x + y}
=> # <Proc: 0x00007fc605ea8698 @ (IRB): 2>
IRB (fő): 003: 0> l.call "hello", "világ"
=> "HelloWorld"
IRB (fő): 004: 0> p.call "hello", "világ"
=> "HelloWorld"
IRB (fő): 005: 0> l.call "szia"
ArgumentError: Az argumentumok száma (1, 2)
    a (IRB): 1
    re (IRB): 5: a `felhívás
    a (IRB): 5
    a: 0
IRB (fő): 006: 0> p.call "szia"
Típushiba: nem lehet átalakítani nulla sztringgé
    a (IRB): 2: a `+”
    a (IRB): 2
    re (IRB): 6: a `felhívás
    a (IRB): 6
    a: 0

Az oldal továbbá azt javasolja, lambda ha kifejezetten szeretné, hogy a hiba toleráns viselkedés. Egyetértek ezzel hangulat. Egy lambda tűnik tad tömörebb, és egy ilyen jelentéktelen különbség, úgy tűnik, a jobb választás az átlagos helyzetet.

Ami a Ruby 1.9, bocs, nem néztem bele 1.9 még, de nem hiszem, akkor változtassa meg, hogy sok minden (nem veszi a szót, hogy bár úgy tűnik, hogy már hallott néhány változás, így valószínűleg én vagyok rosszul van).

Válaszolt 03/08/2008 08:28
a forrás felhasználó

szavazat
364

Egy másik fontos, de finom különbség procs létrehozott lambdaés procs létrehozott Proc.newhogyan kezelik a returnnyilatkozatot:

  • Egy lambda-Által proc, a returnnyilatkozat vissza csak a proc magát
  • Egy Proc.new-Által proc, a returnkijelentés egy kicsit meglepő: ez visszaadja a vezérlést nem csak a proc, hanem a módszer körülzáró proc!

Itt lambda-Által proc féle returnakcióban. Úgy viselkedik, oly módon, hogy valószínűleg számíthat:

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"

Most itt van egy Proc.new-Által proc által returnugyanazt a dolgot. Te arról, hogy az az eset, amikor Ruby megtöri a sokat magasztalt elve Legkisebb Meglepetés:

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"

Ennek köszönhetően a meglepő viselkedés (valamint kevésbé tipizálás), én inkább előnyben segítségével lambdaát Proc.new, ha így speciális képessége.

Válaszolt 03/08/2008 16:21
a forrás felhasználó

szavazat
1

A különbség a viselkedés returnis IMHO a legfontosabb különbség a 2. Én is inkább lambda mert kevesebb gépelés, mint Proc.new :-)

Válaszolt 11/08/2008 03:09
a forrás felhasználó

szavazat
7

Lezárások Ruby egy jó áttekintést, hogyan blokkok, lambda és proc munka Ruby, Ruby.

Válaszolt 28/08/2008 14:50
a forrás felhasználó

szavazat
3

Hogy dolgozza ki harmonika Guy válasza:

Figyeljük meg, hogy Proc.newlétrehoz egy proc ki azáltal, hogy elfogadott egy blokk. Úgy vélem, hogy lambda {...}az elemzett, mint egyfajta szó, hanem egy módszer hívást, amely átmegy a blokk. returnING belülről egy blokk kapcsolódik eljárás hívás visszatér a módszer, nem a blokk, és az Proc.neweset példa e a játék.

(Ez a 1.8. Nem tudom, hogy ez hogyan fordítja 1.9.)

Válaszolt 07/09/2008 03:31
a forrás felhasználó

szavazat
14

Proc idősebb, de a szemantika visszatérés nagyon ellentmondanak nekem (legalábbis amikor én tanultam a nyelvet), mert:

  1. Ha ön használ proc, akkor nagy valószínűséggel igénybe valamilyen funkcionális paradigma.
  2. Proc visszatérhet ki a körülfogó hatályát (lásd az előző válaszok), amely egy Goto alapvetően, és erősen nem-funkcionális jellegű.

Lambda funkcionálisan biztonságosabb és könnyebb esetlapú - Mindig használja, ahelyett, proc.

Válaszolt 11/09/2008 00:32
a forrás felhasználó

szavazat
11

Nem tudok sokat mondani a finom különbségeket. Én azonban rámutatni arra, hogy a Ruby 1.9 már lehetővé teszi opcionális paramétereket lambdas és blokkolja.

Itt az új szintaxist az stabby lambdas alatt 1,9:

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

Ruby 1.8 nem volt, hogy szintaxis. Sem a hagyományos módon nyilvánításáról blokk / lambdas támogatja Választható paraméterek:

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

Ruby 1.9 azonban támogatja az opcionális érvek még a régi szintaxissal:

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

Ha akarsz építeni Ruby1.9 Leopard vagy Linux, nézd meg ezt a cikket (szégyentelen saját promóciós).

Válaszolt 19/11/2008 22:28
a forrás felhasználó

szavazat
9

Egy jó módja annak, hogy van az, hogy lambdas kerülnek végrehajtásra saját hatáskörben (mintha egy eljárás hívás), míg a speciális képessége lehet tekinteni végre inline a hívó módszer, hogy legalább egy jó módja annak eldöntésére amelyiket használni minden egyes esetben.

Válaszolt 09/12/2008 15:17
a forrás felhasználó

szavazat
8

Nem vettem észre semmilyen véleményt a harmadik módszer a queston „proc”, amely elavult, de máshogy kezelik a 1.8 és 1.9.

Itt egy meglehetősen részletes példát, amely megkönnyíti, hogy a különbségek a három hasonló felhívást:

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
Válaszolt 25/06/2009 12:22
a forrás felhasználó

szavazat
93

További felvilágosítást:

Joey azt mondja, hogy a visszatérés viselkedése Proc.newmeglepő. Azonban ha figyelembe vesszük, hogy Proc.new viselkedik, mint egy blokk ez nem meglepő, hiszen ez pontosan hogyan blokkok viselkednek. lambas másrészt úgy viselkednek, mint módszerekkel.

Ez tulajdonképpen megmagyarázza, hogy miért procs rugalmasak, amikor a argumentumainak száma (db érvek), míg lambdas nem. Blocks nem igényelnek minden érveiket kell biztosítani, de a módszerek (kivéve, ha az alapértelmezett biztosított). Miközben a lambda érv alapértelmezett nincs lehetőség a Ruby 1.8, akkor most már támogatja a Ruby 1.9 az alternatív lambda szintaxis (amint azt webmat):

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

És Michiel de Mare (OP) helytelen a speciális képessége és a lambda viselkedik azonos argumentumainak száma Ruby 1.9. Azt igazolták, hogy azok továbbra is fenntartják a viselkedés 1.8 fent meghatározott.

breakállítások valójában nem sok értelme van akár speciális képessége vagy lambdas. A speciális képessége, a szünetben visszatér Önt Proc.new ami már befejeződött. És ez nem semmi értelme, hogy megtörje a lambda, mivel ez alapvetően egy módszert, és soha többé megtörni a legfelső szinten a módszert.

next, redoÉs raiseazonos módon viselkednek mind speciális képessége és lambdas. Mivel retrynem megengedett sem, és növeli a kivétel.

És végül, a procmódszert nem szabad használni, mivel ez következetlen és nem várt viselkedést. A Ruby 1.8 ténylegesen vissza lambda! A Ruby 1.9 ezt már javították, és visszatér a Proc. Ha azt szeretnénk, hogy hozzon létre egy Proc, kibír Proc.new.

További információért ajánlom O'Reilly A Ruby programozási nyelv , amely az én forrása a legtöbb információt.

Válaszolt 04/10/2009 06:23
a forrás felhasználó

szavazat
10

Rövid válasz: Az számít, hogy mit returncsinál: lambda visszatér magából és proc visszatér ki magát, és a funkció, amelyet nevezte.

Ami kevésbé világos, ezért a használni kívánt minden. lambda, amit várunk dolgot kell csinálni egy funkcionális programozási értelme. Ez alapvetően egy névtelen módszer jelenlegi hatálya automatikusan kötve. A kettő közül az egyik lambda akkor valószínűleg használni.

Proc, másrészt, valóban hasznos végrehajtási maga a nyelv. Például lehet végrehajtani „ha” nyilatkozatok vagy „a” hurkok velük. Bármilyen megtérülési megtalálható a proc visszatér ki a módszert nevezte, nem csak a „ha” nyilatkozatot. Így nyelven működik, hogyan „ha” nyilatkozatok dolgozni, így az a gyanúm, Ruby használja ezt a takaró alatt, és ők csak téve azt, mert úgy tűnt erős.

Akkor csak igazán szükség erre, ha új nyelvi konstrukciók, mint a hurkok, if-else konstrukciók, stb

Válaszolt 06/10/2011 19:33
a forrás felhasználó

szavazat
6

Megértése Ruby Blocks, PROC és Lambdas Robert Sosinski világosan megmagyarázza ezeket a programozási koncepciók és megerősíti a magyarázatot példa kódot. Eljárás tárgyak kapcsolódnak egymáshoz, és fedett is.

Válaszolt 23/08/2013 18:07
a forrás felhasználó

szavazat
5

lambda a várt módon működik, mint más nyelveken.

A vezetékes Proc.newmeglepő és zavaró.

Az returnállítás proc létre Proc.newnem csak vissza a vezérlés csak magából, de szintén a módszer körülhatárolunk .

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

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

Akkor azt állítják, hogy Proc.newbeilleszti a kódot a befoglaló módszer, mint blokkot. De Proc.newlétrehoz egy objektumot, míg blokk része egy tárgy.

És van egy másik különbség lambda és Proc.new, ami az ő kezelése (hibás) érveket. lambda panaszkodik rá, miközben Proc.newfigyelmen kívül hagyja extra érvek vagy tartja hiányában érvek hagyni.

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, proca Ruby 1.8 létrehoz egy lambda, míg Ruby 1.9+ viselkedik Proc.new, ami nagyon zavaró.

Válaszolt 29/10/2014 16:22
a forrás felhasználó

szavazat
2

Én egy kicsit későn, de van egy nagy, de kevéssé ismert dolog Proc.newnem említett megjegyzések egyáltalán. Mivel a dokumentáció :

Proc::newnevezhetjük nélkül blokk csak egy módszert egy csatolt blokk, ebben az esetben, hogy a blokk alakítjuk át aProc tárgyat.

Ez azt mondta, Proc.newlehetővé teszi, hogy lánc így módszerek:

def m1
  yield 'Finally!' if block_given?
end

def m2
  m1 &Proc.new
end

m2 { |e| puts e } 
#⇒ Finally!
Válaszolt 28/04/2015 13:15
a forrás felhasználó

szavazat
1

Érdemes hangsúlyozni, hogy returna proc visszatér a lexikailag körülzáró módszerrel, azaz az eljárás, ha a proc jött létre , nem a módszer, hogy az úgynevezett proc. Ez annak a következménye, hogy bezárja tulajdonát speciális képessége. Tehát a következő kódot a kimenet üres:

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

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

foo

Bár a proc végrehajtja foobar, akkor jött létre foo, így a returnkijárat foo, és nem csak foobar. Ahogy Charles Caldwell fentebb írtam, hogy van egy GOTO atmoszféra. Véleményem returnrendben van a blokkban, amely végre saját lexikális kontextusban, de sokkal kevésbé intuitív, ha egy proc, amely végre egy másik összefüggésben.

Válaszolt 15/11/2018 10:00
a forrás felhasználó

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