A Ruby 1.8, vannak finom különbségek proc / lambda egyrészt, és Proc.new
a 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 Ruby 1.8, vannak finom különbségek proc / lambda egyrészt, és Proc.new
a másik oldalon.
Találtam ezt az oldalt , amely megmutatja, hogy mi a különbség Proc.new
, és lambda
vannak. 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).
Egy másik fontos, de finom különbség procs létrehozott lambda
és procs létrehozott Proc.new
hogyan kezelik a return
nyilatkozatot:
lambda
-Által proc, a return
nyilatkozat vissza csak a proc magátProc.new
-Által proc, a return
kijelenté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 return
akció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 return
ugyanazt 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.
A különbség a viselkedés return
is IMHO a legfontosabb különbség a 2. Én is inkább lambda mert kevesebb gépelés, mint Proc.new :-)
Lezárások Ruby egy jó áttekintést, hogyan blokkok, lambda és proc munka Ruby, Ruby.
Hogy dolgozza ki harmonika Guy válasza:
Figyeljük meg, hogy Proc.new
lé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. return
ING belülről egy blokk kapcsolódik eljárás hívás visszatér a módszer, nem a blokk, és az Proc.new
eset példa e a játék.
(Ez a 1.8. Nem tudom, hogy ez hogyan fordítja 1.9.)
Proc idősebb, de a szemantika visszatérés nagyon ellentmondanak nekem (legalábbis amikor én tanultam a nyelvet), mert:
Lambda funkcionálisan biztonságosabb és könnyebb esetlapú - Mindig használja, ahelyett, proc.
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).
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.
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
További felvilágosítást:
Joey azt mondja, hogy a visszatérés viselkedése Proc.new
meglepő. 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 raise
azonos módon viselkednek mind speciális képessége és lambdas. Mivel retry
nem megengedett sem, és növeli a kivétel.
És végül, a proc
mó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.
Rövid válasz: Az számít, hogy mit return
csiná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
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.
lambda a várt módon működik, mint más nyelveken.
A vezetékes Proc.new
meglepő és zavaró.
Az return
állítás proc létre Proc.new
nem 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.new
beilleszti a kódot a befoglaló módszer, mint blokkot. De Proc.new
lé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.new
figyelmen 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, proc
a Ruby 1.8 létrehoz egy lambda, míg Ruby 1.9+ viselkedik Proc.new
, ami nagyon zavaró.
Én egy kicsit későn, de van egy nagy, de kevéssé ismert dolog Proc.new
nem említett megjegyzések egyáltalán. Mivel a dokumentáció :
Proc::new
nevezhetjü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.new
lehető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!
Érdemes hangsúlyozni, hogy return
a 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 return
kijárat foo
, és nem csak foobar
. Ahogy Charles Caldwell fentebb írtam, hogy van egy GOTO atmoszféra. Véleményem return
rendben 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.