Jedna różnica dotyczy sposobu, w jaki radzą sobie z argumentami. Tworzenie proc przy użyciu proc {}i Proc.new {}są równoważne. Jednak użycie lambda {}daje ci proces, który sprawdza liczbę argumentów przekazanych do niego. Od ri Kernel#lambda:
Równoważne z Proc.new , z tym wyjątkiem, że wynikowe obiekty Proc sprawdzają liczbę parametrów przekazanych podczas wywołania.
Przykład:
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)
Ponadto, jak podkreśla Ken, użycie returnwewnątrz lambdy zwraca wartość tej lambdy, ale użycie returnw proc zwraca z otaczającego bloku.
Więc dla większości szybkich zastosowań są takie same, ale jeśli chcesz automatycznie, ścisłe sprawdzanie argumentów (co czasami może pomóc w debugowaniu) lub jeśli potrzebujesz użyć returninstrukcji do zwrócenia wartości proc, użyj lambda.
Czy słuszne byłoby stwierdzenie, że lambdy są bardzo podobne do metod (sprawdzanie argumentów i powrót zwróci z nich), podczas gdy procesy są bardzo podobne do bloków (argumenty nie są sprawdzane, a wynik zwróci z metody zawierającej lub lambdy)?
pedz
Byłem w Bóg jeden wie, ile stron internetowych i artykułów do tej pory i wydaje się, że nikt nie mówi o użyteczności Procs, metod i lambd. Każde wyjaśnienie zawiera tylko rozszczepiające włosy szczegóły dotyczące tego, jak wartości zwracane itp. Są różne, ale nie wyjaśnia, dlaczego ma to znaczenie. Na razie muszę stwierdzić, że w Rubim jest to bałagan projektowy.
ankush981
76
Prawdziwa różnica między procesami a lambdami ma wszystko wspólnego ze słowami kluczowymi przepływu sterowania. Mówię return, raise, break, redo, retryitd. - tymi słowami kontrolnymi. Powiedzmy, że masz instrukcję return w proc. Gdy wywołasz swój proc, nie tylko wyrzuci Cię z niego, ale także wróci z otaczającej metody, np .:
Finał putsw metodzie nigdy nie został wykonany, ponieważ kiedy wywołaliśmy nasz proces, returnjego wnętrze wyrzuciło nas z metody. Jeśli jednak zamienimy nasz proc na lambdę, otrzymamy:
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
Zwrot w lambdzie powoduje tylko wyrzucenie nas z samej lambdy, a otaczająca metoda kontynuuje wykonywanie. Sposób, w jaki słowa kluczowe przepływu sterowania są traktowane w procedurach i lambdach, jest główną różnicą między nimi
Najpierw a lambdasprawdza liczbę przekazanych do niego argumentów, a procnie. Oznacza to, że a lambdazgłosi błąd, jeśli przekażesz mu niewłaściwą liczbę argumentów, podczas gdy a proczignoruje nieoczekiwane argumenty i przypisze nildo tych, których brakuje.
Po drugie, kiedy a lambdapowraca, przekazuje kontrolę z powrotem do metody wywołującej; kiedy a proczwraca, robi to natychmiast, bez wracania do metody wywołującej.
Aby zobaczyć, jak to działa, spójrz na poniższy kod. Nasza pierwsza metoda wywołuje a proc; druga nazywa 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!"
Zobacz, jak procmówi „Batman wygra!”, Ponieważ wraca natychmiast, bez powrotu do metody batman_ironman_proc.
Nasz lambdajednak wraca do metody po wywołaniu, więc metoda zwraca ostatni kod, który ocenia: „Iron Man wygra!”
1. Lambdy sprawdzają liczbę argumentów, podczas gdy procesy nie
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)
W przeciwieństwie do tego, procy nie przejmują się, jeśli przekazano im złą liczbę argumentów.
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. Lambdy i procesy różnie traktują słowo kluczowe „return”
„return” wewnątrz wyrażenia lambda wyzwala kod bezpośrednio poza kodem lambda
A żeby odpowiedzieć na Twoje inne pytanie, którego użyć i kiedy? Będę śledził @jtbandes, jak wspomniał
Więc dla większości szybkich zastosowań są takie same, ale jeśli chcesz automatycznie, ścisłe sprawdzanie argumentów (co czasami może pomóc w debugowaniu) lub jeśli musisz użyć instrukcji return, aby zwrócić wartość proc, użyj lambda.
Mówiąc ogólnie, lambdy są bardziej intuicyjne niż procesy, ponieważ są bardziej podobne do metod. Są dość surowe, jeśli chodzi o arity, i po prostu wychodzą, gdy wywołujesz zwrot. Z tego powodu wielu Rubyistów używa lambd jako pierwszego wyboru, chyba że potrzebują specyficznych cech procs.
Procesy: Obiekty klasy Proc. Podobnie jak bloki, są oceniane w zakresie, w którym zostały zdefiniowane.
Lambdy: Również obiekty klasy, Procale nieznacznie różnią się od zwykłych procesów. Są domknięciami, takimi jak bloki i procesy, i jako takie są oceniane w zakresie, w którym zostały zdefiniowane.
a = proc { |x| x 2 }jest taki sam jaka = Proc.new { |x| x 2 }
lacostenycoder
1
Oto inny sposób, aby to zrozumieć.
Blok to fragment kodu dołączony do wywołania metody na obiekcie. W poniższym przykładzie self jest instancją anonimowej klasy dziedziczącej po ActionView :: Base we frameworku Rails (który sam zawiera wiele modułów pomocniczych). karta to metoda, którą nazywamy siebie. Przekazujemy argument do metody, a następnie zawsze dołączamy blok na końcu wywołania metody:
self.card :contacts do|c|// a chunk of valid ruby code
end
Ok, więc przekazujemy fragment kodu do metody. Ale jak wykorzystujemy ten blok? Jedną z opcji jest przekonwertowanie fragmentu kodu na obiekt. Ruby oferuje trzy sposoby na przekształcenie fragmentu kodu w obiekt
# 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
W powyższej metodzie & konwertuje blok przekazany do metody na obiekt i zapisuje ten obiekt w bloku zmiennej lokalnej. W rzeczywistości możemy pokazać, że zachowuje się tak samo jak lambda i Proc.new:
def add(&block)
block
end
l3 = add {|a| a +1}
l3.call(1)=>2
To jest ważne. Kiedy przekazujesz blok do metody i konwertujesz ją za pomocą &, tworzony przez niego obiekt używa Proc.new do wykonania konwersji.
Zauważ, że unikałem użycia "proc" jako opcji. To dlatego, że jest to Ruby 1.8, jest taki sam jak lambda, aw Ruby 1.9 to to samo, co Proc.new i we wszystkich wersjach Rubiego należy tego unikać.
Więc pytasz jaka jest różnica między lambda i Proc.new?
Po pierwsze, jeśli chodzi o przekazywanie parametrów, lambda zachowuje się jak wywołanie metody. Zgłosi wyjątek, jeśli podasz niewłaściwą liczbę argumentów. Natomiast Proc.new zachowuje się jak przypisanie równoległe. Wszystkie nieużywane argumenty są zamieniane na zero:
> 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+
Po drugie, lambda i Proc.new inaczej obsługują słowo kluczowe return. Kiedy wykonujesz powrót wewnątrz Proc.new, w rzeczywistości wraca on z metody otaczającej, czyli z otaczającego kontekstu. Kiedy wracasz z bloku lambda, po prostu wraca z bloku, a nie z otaczającej metody. Zasadniczo wychodzi z wywołania do bloku i kontynuuje wykonywanie z resztą otaczającej metody.
>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"
Skąd więc ta różnica w zachowaniu? Powodem jest to, że dzięki Proc.new możemy używać iteratorów w kontekście otaczających metod i wyciągać logiczne wnioski. Spójrz na ten przykład:
>def print(max)[1,2,3,4,5].each do|val|
puts val
returnif val > max
endend> print(3)1234
Oczekujemy, że gdy wywołasz return wewnątrz iteratora, zwróci on z otaczającej metody. Pamiętaj, że bloki przekazywane do iteratorów są konwertowane na obiekty przy użyciu Proc.new i dlatego kiedy używamy return, zakończy on otaczającą metodę.
Możesz myśleć o lambdach jako o metodach anonimowych, izolują one poszczególne bloki kodu w obiekt, który można traktować jak metodę. Ostatecznie pomyśl, że lambda zachowuje się jak anomiczna metoda, a Proc.new zachowuje się jak kod wbudowany.
różnica między proc a lambda polega na tym, że proc jest po prostu kopią kodu z zastępowanymi argumentami po kolei, podczas gdy lambda jest funkcją podobną do innych języków. (zachowanie zwrotu, sprawdzenie argumentów)
return
powraca oświadczenie wproc
porównaniulambda
.Odpowiedzi:
Jedna różnica dotyczy sposobu, w jaki radzą sobie z argumentami. Tworzenie proc przy użyciu
proc {}
iProc.new {}
są równoważne. Jednak użycielambda {}
daje ci proces, który sprawdza liczbę argumentów przekazanych do niego. Odri Kernel#lambda
:Przykład:
Ponadto, jak podkreśla Ken, użycie
return
wewnątrz lambdy zwraca wartość tej lambdy, ale użyciereturn
w proc zwraca z otaczającego bloku.Więc dla większości szybkich zastosowań są takie same, ale jeśli chcesz automatycznie, ścisłe sprawdzanie argumentów (co czasami może pomóc w debugowaniu) lub jeśli potrzebujesz użyć
return
instrukcji do zwrócenia wartości proc, użyjlambda
.źródło
Prawdziwa różnica między procesami a lambdami ma wszystko wspólnego ze słowami kluczowymi przepływu sterowania. Mówię
return
,raise
,break
,redo
,retry
itd. - tymi słowami kontrolnymi. Powiedzmy, że masz instrukcję return w proc. Gdy wywołasz swój proc, nie tylko wyrzuci Cię z niego, ale także wróci z otaczającej metody, np .:Finał
puts
w metodzie nigdy nie został wykonany, ponieważ kiedy wywołaliśmy nasz proces,return
jego wnętrze wyrzuciło nas z metody. Jeśli jednak zamienimy nasz proc na lambdę, otrzymamy:Zwrot w lambdzie powoduje tylko wyrzucenie nas z samej lambdy, a otaczająca metoda kontynuuje wykonywanie. Sposób, w jaki słowa kluczowe przepływu sterowania są traktowane w procedurach i lambdach, jest główną różnicą między nimi
źródło
Istnieją tylko dwie główne różnice.
lambda
sprawdza liczbę przekazanych do niego argumentów, aproc
nie. Oznacza to, że alambda
zgłosi błąd, jeśli przekażesz mu niewłaściwą liczbę argumentów, podczas gdy aproc
zignoruje nieoczekiwane argumenty i przypiszenil
do tych, których brakuje.lambda
powraca, przekazuje kontrolę z powrotem do metody wywołującej; kiedy aproc
zwraca, robi to natychmiast, bez wracania do metody wywołującej.Aby zobaczyć, jak to działa, spójrz na poniższy kod. Nasza pierwsza metoda wywołuje a
proc
; druga nazywa alambda
.Zobacz, jak
proc
mówi „Batman wygra!”, Ponieważ wraca natychmiast, bez powrotu do metody batman_ironman_proc.Nasz
lambda
jednak wraca do metody po wywołaniu, więc metoda zwraca ostatni kod, który ocenia: „Iron Man wygra!”źródło
# Przykłady procesów
# Przykłady lambda
Różnice między procesami a lambdami
Zanim przejdę do różnic między procesami a lambdami, ważne jest, aby wspomnieć, że oba są obiektami Proc.
Jednak lambdy to inny „smak” procesów. Ta niewielka różnica jest widoczna podczas zwracania obiektów.
1. Lambdy sprawdzają liczbę argumentów, podczas gdy procesy nie
W przeciwieństwie do tego, procy nie przejmują się, jeśli przekazano im złą liczbę argumentów.
2. Lambdy i procesy różnie traktują słowo kluczowe „return”
„return” wewnątrz wyrażenia lambda wyzwala kod bezpośrednio poza kodem lambda
'return' wewnątrz proca wyzwala kod poza metodą, w której proc jest wykonywany
A żeby odpowiedzieć na Twoje inne pytanie, którego użyć i kiedy? Będę śledził @jtbandes, jak wspomniał
Pierwotnie opublikowane tutaj
źródło
Mówiąc ogólnie, lambdy są bardziej intuicyjne niż procesy, ponieważ są bardziej podobne do metod. Są dość surowe, jeśli chodzi o arity, i po prostu wychodzą, gdy wywołujesz zwrot. Z tego powodu wielu Rubyistów używa lambd jako pierwszego wyboru, chyba że potrzebują specyficznych cech procs.
Procesy: Obiekty klasy
Proc
. Podobnie jak bloki, są oceniane w zakresie, w którym zostały zdefiniowane. Lambdy: Również obiekty klasy,Proc
ale nieznacznie różnią się od zwykłych procesów. Są domknięciami, takimi jak bloki i procesy, i jako takie są oceniane w zakresie, w którym zostały zdefiniowane.Tworzenie proc
Tworzenie lambdy
b = lambda { |x| x 2
}źródło
a = proc { |x| x 2 }
jest taki sam jaka = Proc.new { |x| x 2 }
Oto inny sposób, aby to zrozumieć.
Blok to fragment kodu dołączony do wywołania metody na obiekcie. W poniższym przykładzie self jest instancją anonimowej klasy dziedziczącej po ActionView :: Base we frameworku Rails (który sam zawiera wiele modułów pomocniczych). karta to metoda, którą nazywamy siebie. Przekazujemy argument do metody, a następnie zawsze dołączamy blok na końcu wywołania metody:
Ok, więc przekazujemy fragment kodu do metody. Ale jak wykorzystujemy ten blok? Jedną z opcji jest przekonwertowanie fragmentu kodu na obiekt. Ruby oferuje trzy sposoby na przekształcenie fragmentu kodu w obiekt
W powyższej metodzie & konwertuje blok przekazany do metody na obiekt i zapisuje ten obiekt w bloku zmiennej lokalnej. W rzeczywistości możemy pokazać, że zachowuje się tak samo jak lambda i Proc.new:
To jest ważne. Kiedy przekazujesz blok do metody i konwertujesz ją za pomocą &, tworzony przez niego obiekt używa Proc.new do wykonania konwersji.
Zauważ, że unikałem użycia "proc" jako opcji. To dlatego, że jest to Ruby 1.8, jest taki sam jak lambda, aw Ruby 1.9 to to samo, co Proc.new i we wszystkich wersjach Rubiego należy tego unikać.
Więc pytasz jaka jest różnica między lambda i Proc.new?
Po pierwsze, jeśli chodzi o przekazywanie parametrów, lambda zachowuje się jak wywołanie metody. Zgłosi wyjątek, jeśli podasz niewłaściwą liczbę argumentów. Natomiast Proc.new zachowuje się jak przypisanie równoległe. Wszystkie nieużywane argumenty są zamieniane na zero:
Po drugie, lambda i Proc.new inaczej obsługują słowo kluczowe return. Kiedy wykonujesz powrót wewnątrz Proc.new, w rzeczywistości wraca on z metody otaczającej, czyli z otaczającego kontekstu. Kiedy wracasz z bloku lambda, po prostu wraca z bloku, a nie z otaczającej metody. Zasadniczo wychodzi z wywołania do bloku i kontynuuje wykonywanie z resztą otaczającej metody.
Skąd więc ta różnica w zachowaniu? Powodem jest to, że dzięki Proc.new możemy używać iteratorów w kontekście otaczających metod i wyciągać logiczne wnioski. Spójrz na ten przykład:
Oczekujemy, że gdy wywołasz return wewnątrz iteratora, zwróci on z otaczającej metody. Pamiętaj, że bloki przekazywane do iteratorów są konwertowane na obiekty przy użyciu Proc.new i dlatego kiedy używamy return, zakończy on otaczającą metodę.
Możesz myśleć o lambdach jako o metodach anonimowych, izolują one poszczególne bloki kodu w obiekt, który można traktować jak metodę. Ostatecznie pomyśl, że lambda zachowuje się jak anomiczna metoda, a Proc.new zachowuje się jak kod wbudowany.
źródło
Pomocny post o przewodnikach po Ruby: blokach, procesach i lambdach
źródło
różnica między proc a lambda polega na tym, że proc jest po prostu kopią kodu z zastępowanymi argumentami po kolei, podczas gdy lambda jest funkcją podobną do innych języków. (zachowanie zwrotu, sprawdzenie argumentów)
źródło