block vs proc vs lambda
Blocks, Procs, and lambdas are all constructs in Ruby that allow us to encapsulate and pass around blocks of code. They provide a way to write reusable and flexible code.
Blocks: Blocks are chunks of code that can be passed to methods in Ruby. They are not objects and cannot be assigned to variables or passed independently. Blocks are often used with iterator methods such as
each
ormap
. Blocks are defined within a method call using{ }
ordo ... end
syntax.
Here's an example of a block being passed to the each
method:
numbers = [1, 2, 3, 4, 5]
numbers.each { |num| puts num }
In this example, the block { |num| puts num }
is passed to the each
method of the numbers
array. The block is executed for each element in the array, printing the value of each number.
Procs: Procs are objects that encapsulate blocks of code and allow them to be stored in variables, passed as arguments, or returned from methods. They provide a way to reuse blocks of code. Procs are created using the
Proc.new
orproc
method, or by using thelambda
keyword.
Here's an example of a Proc being assigned to a variable and invoked later:
greeting = Proc.new { puts "Hello!" }
greeting.call # Output: Hello!
# named parameter
hello_proc = proc { |name| puts "Hello, #{name}!" }
hello_proc.call("Alice") # Output: Hello, Alice!
In this example, the Proc.new { puts "Hello!" }
creates a Proc object that prints "Hello!". The Proc is assigned to the variable greeting
, and we can invoke it later using the call
method.
Lambdas: Lambdas are similar to Procs in that they encapsulate blocks of code and can be stored in variables or passed as arguments. However, lambdas have slight differences in behavior compared to Procs. Lambdas are created using the
->
syntax or thelambda
keyword.
Here's an example of a lambda being passed as an argument to a method:
# lambda with params
hello_lambda = lambda { |name| puts "Hello, #{name}!" }
hello_lambda.call("Bob") # Output: Hello, Bob!
# another examplecode
greet = -> { puts "Hello!" }
def execute_lambda(lambda)
lambda.call
end
execute_lambda(greet)
In this example, the lambda -> { puts "Hello!" }
is passed as an argument to the execute_lambda
method. Inside the method, the lambda is invoked using the call
method, resulting in the output "Hello!".
The main difference between Procs and lambdas is how they handle argument checking and return behavior.
Lambdas perform strict argument checking, while Procs perform loose argument checking.
Additionally, lambdas return from themselves, while Procs return from the method that encloses them.
def greeting_with_proc
hello_proc = proc { return "Hello from proc!" }
hello_proc.call
puts "This will not be printed."
end
def greeting_with_lambda
hello_lambda = lambda { return "Hello from lambda!" }
hello_lambda.call
puts "This will be printed."
end
puts greeting_with_proc # Output: Hello from proc!
puts greeting_with_lambda # Output: Hello from lambda!
Understanding blocks, Procs, and lambdas is essential for writing more flexible and reusable code in Ruby, especially in scenarios where we need to pass behavior as an argument to methods or store it in variables.
Last updated