To są trzy sposoby, w jakie Ruby obsługuje fragmenty kodu jako dane. Blok jest przekazywany metodzie (nie jest obiektem); Proc i lambda to obiekty, które opakowują blok (wywoływalne, przechowywalne). Procs i lambdy różnią się subtelnie w zakresie sprawdzania argumentów i zachowania return.
Bloki — przekazywane metodom (nie obiekty)
[1, 2, 3].each { |n| puts n } # the { } is a block — passed to each
# a block is NOT an object; it's part of the method call, can't be stored in a variable directly
Blok to kod przekazany metodzie (w { } lub do...end) — nie jest to samodzielny obiekt, który można przechowywać; jest powiązany z wywołaniem metody.
Procs i lambdy — bloki jako przechowywalne obiekty
# a Proc — a block turned into an object you can store and call
square = Proc.new { |x| x * x }
square.call(5) # 25
square.(5) # 25 (alternate call syntax)
# a lambda — also a callable object (a "stricter" Proc)
double = lambda { |x| x * 2 }
double = ->(x) { x * 2 } # the -> "stabby lambda" syntax
double.call(5) # 10
Procs i lambdy opakowują blok w obiekt, który można przypisać zmiennym, przekazywać dalej i wywoływać później (.call) — przydatne do przechowywania wielokrotnie używanego zachowania.
Kluczowe różnice: argumenty i return
1. ARGUMENT CHECKING:
lambda → STRICT: errors if wrong number of arguments (like a method)
proc → LENIENT: ignores extra args, fills missing with nil
2. RETURN behavior:
lambda → `return` returns from the LAMBDA (like a normal method)
proc → `return` returns from the ENCLOSING METHOD (can surprise you!)
def test_proc
p = Proc.new { return 10 }
p.call # returns from test_proc ENTIRELY → 10
return 20 # never reached!
end
def test_lambda
l = lambda { return 10 }
l.call # returns from the LAMBDA only → 10
return 20 # reached → test_lambda returns 20
end
Najważniejsza różnica: lambda zachowuje się jak metoda (ścisłe argumenty, return wychodzi tylko z lambdy), podczas gdy proc jest bardziej liberalny (ignoruje niezgodności argumentów, a return wychodzi z otaczającej metody — co może spowodować zaskakujące zachowanie). Lambdy są ogólnie preferowane ze względu na ich zachowanie podobne do metod, przejrzysty charakter.
Dlaczego to ważne
Zrozumienie bloków, proców i lambd — a szczególnie ich różnic — to ważna wiedza o Ruby'ego, która odzwierciedla głębsze zrozumienie, jak Ruby obsługuje kod jako dane. Bloki są najczęściej używane (przekazywane metodom do iteracji i callbacków — to sygnatura Ruby'ego), natomiast procs i lambdy zamieniają bloki na przechowywalne, wielokrotnie używalne obiekty, które można przypisywać zmiennym, przekazywać dalej i wywoływać później (przydatne do przechowywania zachowania, budowania wzorców funkcjonalnych i przekazywania callbacków jako wartości).
Kluczowe różnice między procami a lambdami są subtelne, ale ważne i często pojawiają się w rozmowach rekrutacyjnych: sprawdzanie argumentów (lambdy są ścisłe jak metody, procs są liberalne) i szczególnie zachowanie return (powrót lambdy wychodzi tylko z lambdy, podczas gdy powrót proca wychodzi z otaczającej metody — co może spowodować zaskakujące, trudne do debugowania zachowanie).
Zrozumienie tych rozróżnień — że lambda zachowuje się jak metoda (ścisła, przejrzysta, z lokalnym powrotem) podczas gdy proc jest bardziej liberalny ze zaskakującą semantyką return — jest ważne dla prawidłowego ich użycia i dla powszechnego zalecenia preferowania lambd ze względu na ich przejrzysty, podobny do metody charakter.
O ile bloki są codziennością w Ruby'ego a procs/lambdy są używane do przechowywanych callbacków i wzorców funkcjonalnych, zrozumienie wszystkich trzech (szczególnie różnic w powrocie i argumentach proc vs lambda) odzwierciedla solidną wiedzę o Ruby'ego, pomaga uniknąć pułapki proc-return i jest klasycznym tematem rozmowy kwalifikacyjnej, który wyróżnia deweloperów, którzy naprawdę rozumieją, jak Ruby obsługuje kod jako obiekty.
