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

ویژگیProcLambda
بررسی تعداد آرگومان❌ بررسی نمی‌کند✅ بررسی می‌کند
رفتار returnاز متد خارج می‌شودفقط از خودش خارج می‌شود
کلاسProcProc (نوع 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 استفاده کنید وقتی:
  • انعطاف بیشتری می‌خواهید
  • بلوک را ذخیره می‌کنید

خلاصه

مفهومسینتکس
ProcProc.new { } یا proc { }
Lambdalambda { } یا ->() { }
فراخوانی.call یا .() یا []
به عنوان بلوکmethod(&proc)

این مبحث بخشی از دوره آموزش کامل روبی است.

ابزارهای مرتبط