Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
W Ruby Proc to obiekt, który przechowuje fragment kodu (blok) i pozwala na jego późniejsze wykonanie. To jak "zapisany blok" lub "funkcja w pudełku".
Przykład 1: tworzymy Proc
say_hello = Proc.new { puts "Hello!" }
say_hello.call
# => "Hello!"
Stworzyliśmy obiekt Proc, który przechowuje kod { puts "Hello!" }. Następnie wywołaliśmy go za pomocą .call.
Przykład 2: przekazujemy Proc do metody
def run_twice(proc)
proc.call
proc.call
end
run_twice(Proc.new { puts "Hi!" })
# => "Hi!"
# => "Hi!"
Przekazaliśmy blok kodu jako obiekt i wywołaliśmy go kilka razy. To bardzo wygodne, gdy trzeba ponownie wykorzystać logikę.
Proc - dlaczego taka nazwa?
Łatwiej zapamiętywać nazwy metod, gdy wiesz, co one oznaczają. Nazwa Proc w Ruby to skrót od "Procedure" (procedura). W językach programowania, jeszcze od czasów Lisp i Scheme, termin procedure oznaczał "fragment kodu, który można wykonać później" - czyli funkcję, którą można przekazać jako argument lub wywołać.
Kiedy Matzumoto (Matz), twórca Ruby, projektował język, chciał, aby Ruby miał prosty i elastyczny sposób pracy z blokami kodu. Wziął pomysł procedur z Lisp/Scheme i uczynił je obiektami - tak powstała klasa Proc (procedure object).
Co to jest Lambda?
Lambda to też Proc, ale z pewnymi różnicami. Można ją stworzyć na kilka sposobów:
-> { }
say_hi = -> { puts "Hi!" }
say_hi.call
# => "Hi!"
oraz lambda {}
say_hello = lambda { puts "Hello!" }
Aby udowodnić, że lambda to proc:
say_hi.class => Proc
Podstawowa różnica między Proc a Lambda
1. Lambda sprawdza liczbę argumentów, a Proc - nie.
p1 = Proc.new { |a, b| puts a, b }
l1 = ->(a, b) { puts a, b }
p1.call(1)
# => 1
# => nil (drugi argument to po prostu nil)
l1.call(1)
# => ArgumentError: wrong number of arguments
2. return w Proc wychodzi z całej metody, a nie tylko z Proc. W Lambda return kończy tylko samą lambdę.
Przyjrzyjmy się przykładom
def test_proc
p = Proc.new { return "From Proc" }
p.call
"After Proc" # ten wiersz nie zostanie wykonany
end
puts test_proc
# => "From Proc"
Kiedy Proc wywołuje return, natychmiast wychodzi z metody, w której został stworzony Proc, a nie tylko z bloku.
return w Lambda kończy tylko samą lambdę
def test_lambda
l = -> { return "From Lambda" }
result = l.call
"After Lambda: #{result}" # ten wiersz zostanie wykonany
end
puts test_lambda
# => "After Lambda: From Lambda"
Lambda zachowuje się jak zwykła metoda: return kończy tylko samą lambdę, a metoda kontynuuje wykonanie dalej.
& i to_proc
Kiedy przekazujesz w Ruby obiekt z ampersandem &, Ruby próbuje wywołać na nim .to_proc i używa otrzymanego Proc jako bloku.
def run(&block)
block.call
end
run { puts "Works!" }
# => "Works!"
Tutaj Ruby automatycznie wywołał .to_proc dla naszego bloku { ... } i przekazał go do zmiennej block.
Ten post nie ma jeszcze żadnych dodatków od autora.