Ruby Lambda
Anonymous functions with strict argument checking
λ What are Ruby Lambdas?
Lambdas are anonymous functions that can be stored in variables and passed around. They check argument counts strictly and return to the calling method, making them predictable and safe.
# Create a lambda
greet = lambda { |name| puts "Hello, #{name}!" }
# Call the lambda
greet.call("Alice")
# Shorter syntax
square = ->(x) { x * x }
puts square.call(5)
Output:
Hello, Alice!
25
Key Lambda Features
Object
Lambdas are objects you can store
add = lambda { |a, b| a + b }
result = add.call(2, 3)
Strict Args
Checks argument count
fn = ->(x) { x * 2 }
fn.call(5) # Works
# fn.call() raises error
Return
Returns to calling method
fn = -> { return 42 }
fn.call # Returns 42
Syntax
Two ways to create lambdas
lambda { |x| x }
->(x) { x }
🔹 Creating Lambdas
Ruby provides two syntaxes for creating lambdas: the traditional lambda keyword and the stabby lambda (->). Both create identical objects, but the stabby syntax is more concise and commonly preferred in modern Ruby code.
# Traditional lambda syntax
greet = lambda { |name| "Hello, #{name}!" }
puts greet.call("Bob")
# Stabby lambda syntax (->)
multiply = ->(a, b) { a * b }
puts multiply.call(4, 5)
# Lambda without parameters
say_hi = -> { "Hi there!" }
puts say_hi.call
# Multi-line lambda
calculate = lambda do |x, y|
sum = x + y
product = x * y
"Sum: #{sum}, Product: #{product}"
end
puts calculate.call(3, 4)
Output:
Hello, Bob!
20
Hi there!
Sum: 7, Product: 12
🔹 Calling Lambdas
Lambdas can be invoked using multiple methods: .call(), square brackets [], or parentheses (). All three work identically, but .call() is most explicit and commonly used for clarity in production code.
# Create a lambda
double = ->(x) { x * 2 }
# Method 1: .call()
puts double.call(5)
# Method 2: Square brackets
puts double[6]
# Method 3: Parentheses (Ruby 1.9+)
puts double.(7)
# With multiple arguments
add = ->(a, b, c) { a + b + c }
puts add.call(1, 2, 3)
puts add[10, 20, 30]
Output:
10
12
14
6
60
🔹 Strict Argument Checking
Unlike Procs, lambdas enforce strict argument checking. If you pass the wrong number of arguments, Ruby raises an ArgumentError. This strictness helps catch bugs early and makes code more predictable and maintainable.
# Lambda requires exact arguments
greet = ->(name, age) { "#{name} is #{age}" }
# Correct number of arguments
puts greet.call("Alice", 25)
# Wrong number causes error (commented to prevent crash)
# greet.call("Bob") # ArgumentError: wrong number of arguments
# Default parameters work
welcome = ->(name, greeting = "Hello") { "#{greeting}, #{name}!" }
puts welcome.call("Charlie")
puts welcome.call("Diana", "Hi")
# Optional parameters with splat
sum = ->(*numbers) { numbers.sum }
puts sum.call(1, 2, 3)
puts sum.call(10, 20)
Output:
Alice is 25
Hello, Charlie!
Hi, Diana!
6
30
🔹 Lambdas as Arguments
Lambdas can be passed to methods as arguments, enabling powerful functional programming patterns. This allows you to inject custom behavior into methods, creating flexible and reusable code structures for callbacks and transformations.
# Pass lambda to method
def apply_operation(a, b, operation)
operation.call(a, b)
end
add = ->(x, y) { x + y }
multiply = ->(x, y) { x * y }
puts apply_operation(5, 3, add)
puts apply_operation(5, 3, multiply)
# Array methods with lambdas
numbers = [1, 2, 3, 4, 5]
is_even = ->(n) { n.even? }
evens = numbers.select(&is_even)
puts "Evens: #{evens.inspect}"
double = ->(n) { n * 2 }
doubled = numbers.map(&double)
puts "Doubled: #{doubled.inspect}"
Output:
8
15
Evens: [2, 4]
Doubled: [2, 4, 6, 8, 10]
🔹 Returning Lambdas
Methods can return lambdas, creating closures that remember their surrounding context. This powerful feature enables factory patterns, currying, and creating specialized functions dynamically based on runtime conditions.
# Method returns a lambda
def multiplier(factor)
->(n) { n * factor }
end
times_two = multiplier(2)
times_three = multiplier(3)
puts times_two.call(5)
puts times_three.call(5)
# Lambda factory
def greeter(greeting)
->(name) { "#{greeting}, #{name}!" }
end
say_hello = greeter("Hello")
say_hi = greeter("Hi")
puts say_hello.call("Alice")
puts say_hi.call("Bob")
# Closure example
def counter
count = 0
-> { count += 1 }
end
increment = counter
puts increment.call
puts increment.call
puts increment.call
Output:
10
15
Hello, Alice!
Hi, Bob!
1
2
3
🔹 Practical Lambda Examples
Lambdas excel in real-world scenarios like data validation, transformation pipelines, and callback systems. These examples show how lambdas create clean, testable code for common programming patterns in Ruby applications.
# Validation lambdas
is_valid_email = ->(email) { email.include?("@") && email.include?(".") }
is_valid_age = ->(age) { age >= 18 && age <= 100 }
puts is_valid_email.call("[email protected]")
puts is_valid_age.call(25)
# Data transformation pipeline
trim = ->(str) { str.strip }
upcase = ->(str) { str.upcase }
add_prefix = ->(str) { "USER: #{str}" }
process = ->(input) {
result = trim.call(input)
result = upcase.call(result)
add_prefix.call(result)
}
puts process.call(" alice ")
# Calculator with lambdas
operations = {
add: ->(a, b) { a + b },
subtract: ->(a, b) { a - b },
multiply: ->(a, b) { a * b },
divide: ->(a, b) { b != 0 ? a / b : "Error" }
}
puts operations[:add].call(10, 5)
puts operations[:multiply].call(4, 3)
Output:
true
true
USER: ALICE
15
12