Block
Blocks are a set of instructions that can be passed to a method for execution. They are enclosed in a do-end
block or between curly braces {}
. Blocks can take multiple arguments, and their argument names are defined between two pipe characters ||
.
Here's an example of a block that we can pass to the each method:
[1, 2, 3].each { |num| puts num }
In the above code, |num|
is the argument of the block, and puts num
is the instruction that will be executed on each element of the array.
Yield
Yield is a Ruby keyword that executes a block of code passed to a method. The code inside the block will run when you use the yield
keyword.
Here's an example of a method that takes a block and uses the yield keyword to execute it:
def print_hello
yield
end
print_hello { puts "Hello" }
In this example, the yield
statement will execute the code inside the block and print "Hello" to the console.
You can also pass arguments to yield:
def one_two_three
yield 1
yield 2
yield 3
end
one_two_three { |number| puts number * 2 }
# 2, 4, 6
Here, we are passing the numbers 1, 2, and 3 to the block and printing their multiples of 2 to the console.
Implicit vs Explicit Blocks
There are two ways to define a block in Ruby: implicit and explicit. An implicit block is not given a name in the parameter list. It is called using the yield keyword. On the other hand, an explicit block is given a name in the parameter list.
Here's an example of an explicit block:
def explicit_block(&block)
block.call # same as yield
end
explicit_block { puts "Explicit block called" }
In the above example, the &block
parameter is used to define the block's name. This allows us to pass the block to another method or save it into a variable to use later.
If you try to yield
without a block, you will get a no block given (yield)
error. To check if a block has been passed in, you can use the block_given?
method.
Lambda
A lambda is a way to define a block and its parameters using a special syntax. A lambda can take arguments, and it won't run the code inside it until you call it using the call
method.
Here's an example of a lambda:
hello_world = -> { puts "Hello world" }
hello_world.call
# "Hello World"
Lambdas can also take arguments, just like methods:
times_two = ->(x) { x * 2 }
times_two.call(10)
# 20
If you pass the wrong number of arguments to a lambda
, it will raise an exception, just like a regular method.
Lambdas vs Procs
Procs are a very similar concept to lambdas, but with a few key differences. One of the differences is how you create them:
my_proc = Proc.new { |x| puts x }
A proc behaves differently than a lambda, especially when it comes to arguments. A proc will not raise an exception if you pass the wrong number of arguments to it:
my_proc.call(1, 2, 3) # prints 1
In this example, the proc only takes one argument, but we passed in three. The extra arguments are ignored.
Another difference between procs and lambdas is how they react to a return
statement. A lambda will return
normally, like a regular method. But a proc will try to return
from the current context:
def test_proc
my_proc = Proc.new { return "returning from proc" }
my_proc.call
return "returning from method"
end
def test_lambda
my_lambda = -> { return "returning from lambda" }
my_lambda.call
return "returning from method"
end
puts test_proc # prints "returning from proc"
puts test_lambda # prints "returning from method"
In this example, the test_proc
method returns from the proc instead of continuing to execute the method. The test_lambda
method, on the other hand, returns normally because the lambda behaves like a regular method.
Top comments (0)