ЗмістНатисність на посилання, щоб перейти до потрібного місця
У Ruby Proc - це об’єкт, який зберігає шматок коду (блок) і дозволяє виконувати його пізніше. Це як "збережений блок" або "функція в коробці".
Приклад 1: створюємо Proc
say_hello = Proc.new { puts "Hello!" }
say_hello.call
# => "Hello!"
Ми створили об’єкт Proc, який зберігає код { puts "Hello!" }. Потім викликали його через .call.
Приклад 2: передаємо Proc у метод
def run_twice(proc)
proc.call
proc.call
end
run_twice(Proc.new { puts "Hi!" })
# => "Hi!"
# => "Hi!"
Ми передали блок коду як об’єкт і викликали його кілька разів. Це дуже зручно, коли потрібно повторно використовувати логіку.
Proc - чому така назва?
Легше запам'ятовувати назви методів, коли знаєш що воно означає. Назва Proc у Ruby - це скорочення від "Procedure" (процедура). У мовах програмування, ще з часів Lisp і Scheme, термін procedure означав "шматок коду, який можна виконати пізніше" - тобто функцію, яку можна передати як аргумент або викликати.
Коли Мацумото (Matz), творець Ruby, проєктував мову, він хотів, щоб Ruby мав простий і гнучкий спосіб роботи з блоками коду. Він узяв ідею процедур із Lisp/Scheme і зробив їх об’єктами - так з’явився клас Proc (procedure object).
Що таке Lambda?
Lambda - це теж Proc, але з деякими відмінностями. Її можна створити кількома способами:
-> { }
say_hi = -> { puts "Hi!" }
say_hi.call
# => "Hi!"
та lambda {}
say_hello = lambda { puts "Hello!" }
Ну а щоб довести, що лямбда це прок:
say_hi.class => Proc
Основна різниця між Proc і Lambda
1. Lambda перевіряє кількість аргументів, а Proc - ні.
p1 = Proc.new { |a, b| puts a, b }
l1 = ->(a, b) { puts a, b }
p1.call(1)
# => 1
# => nil (другий аргумент просто nil)
l1.call(1)
# => ArgumentError: wrong number of arguments
2. return у Proc виходить із всього методу, а не лише з Proc. У Lambda return завершує тільки саму лямбду.
І розглянемо приклади
def test_proc
p = Proc.new { return "From Proc" }
p.call
"After Proc" # цей рядок не виконається
end
puts test_proc
# => "From Proc"
Коли Proc викликає return, він одразу виходить із методу, у якому створений Proc, а не лише з блоку.
return у Lambda завершує тільки саму лямбду
def test_lambda
l = -> { return "From Lambda" }
result = l.call
"After Lambda: #{result}" # цей рядок виконається
end
puts test_lambda
# => "After Lambda: From Lambda"
Лямбда поводиться як звичайний метод: return завершує лише саму лямбду, а метод продовжує виконання далі.
& і to_proc
Коли ви передаєте у Ruby об’єкт із амперсандом &, Ruby робить спробу викликати на ньому .to_proc і використовує отриманий Proc як блок.
def run(&block)
block.call
end
run { puts "Works!" }
# => "Works!"
Тут Ruby автоматично викликав .to_proc для нашого блоку { ... } і передав його в змінну block.
Цей допис поки що не має жодних доповнень від автора/ки.