Proc و Lambda در روبی
تعریف Proc و Lambda، تفاوتها، closure و کاربردهای آنها
Proc و Lambda چیست؟
Proc و Lambda دو روش برای ذخیره یک بلوک کد در یک متغیر هستند. اینها مثل «توابع ناشناس» (Anonymous Functions) عمل میکنند.
تعریف Proc
# با Proc.new
my_proc = Proc.new { |name| puts "سلام #{name}!" }
# با proc
my_proc2 = proc { |x| x ** 2 }
# فراخوانی
my_proc.call("علی") # => سلام علی!
my_proc.("علی") # => سلام علی!
my_proc["علی"] # => سلام علی!
تعریف Lambda
# با lambda
my_lambda = lambda { |name| puts "سلام #{name}!" }
# با -> (arrow syntax)
my_lambda2 = ->(x) { x ** 2 }
# فراخوانی
my_lambda.call("علی")
my_lambda.("علی")
my_lambda["علی"]
تفاوت Proc و Lambda
| ویژگی | Proc | Lambda |
|---|---|---|
| بررسی تعداد آرگومان | ❌ بررسی نمیکند | ✅ بررسی میکند |
| رفتار return | از متد خارج میشود | فقط از خودش خارج میشود |
| کلاس | Proc | Proc (نوع Lambda) |
تفاوت ۱: بررسی آرگومان
# Lambda — بررسی میکند
my_lambda = ->(a, b) { a + b }
my_lambda.call(1, 2) # => 3
# my_lambda.call(1) # => ❌ خطا! آرگومان کم است
# Proc — بررسی نمیکند
my_proc = Proc.new { |a, b| a + b }
my_proc.call(1) # => 1 (b = nil، 1 + nil خطا میدهد)
my_proc.call(1, 2, 3) # => 3 (آرگومان اضافه نادیده گرفته میشود)
تفاوت ۲: رفتار return
def test_proc
my_proc = Proc.new { return 1 }
my_proc.call
return 2 # این خط اجرا نمیشود!
end
def test_lambda
my_lambda = lambda { return 1 }
my_lambda.call # return فقط از lambda خارج میشود
return 2 # این خط اجرا میشود
end
puts test_proc # => 1
puts test_lambda # => 2
Closure
Proc و Lambda متغیرهای محیط اطراف خود را به خاطر میسپارند:
counter = 0
increment = lambda do
counter += 1
end
puts increment.call # => 1
puts increment.call # => 2
puts increment.call # => 3
puts counter # => 3
استفاده به عنوان بلوک (&)
# تبدیل Proc به بلوک
my_proc = Proc.new { |n| n ** 2 }
result = [1, 2, 3].map(&my_proc)
puts result.inspect # => [1, 4, 9]
# تبدیل Lambda به بلوک
my_lambda = ->(n) { n * 2 }
result = [1, 2, 3].map(&my_lambda)
puts result.inspect # => [2, 4, 6]
متد method (تبدیل متد به Proc)
def greet(name)
"سلام #{name}!"
end
greet_method = method(:greet)
puts greet_method.call("علی") # => سلام علی!
# به عنوان بلوک
puts ["علی", "مریم"].map(&greet_method).inspect
# => ["سلام علی!", "سلام مریم!"]
چه زمان از کدام استفاده کنیم؟
✅ از Lambda استفاده کنید وقتی:
- میخواهید بررسی آرگومان داشته باشید
- میخواهید return فقط از خودش باشد
- رفتار شبیه متد میخواهید
- انعطاف بیشتری میخواهید
- بلوک را ذخیره میکنید
خلاصه
| مفهوم | سینتکس |
|---|---|
| Proc | Proc.new { } یا proc { } |
| Lambda | lambda { } یا ->() { } |
| فراخوانی | .call یا .() یا [] |
| به عنوان بلوک | method(&proc) |
این مبحث بخشی از دوره آموزش کامل روبی است.