In Ruby, following are the two ways in which we can pass a block to a method:
- As an argument
- As an anonymous block
Passing an argument is always considered better then anonymous block for various reasons:
- It increases readability of the method.
- If we pass block as an argument, then we get
&block
asProc
object. And in comparision to object, we can not do much with anonymous block.
Let’s define a method that calls a Proc
.
# proc in a method
def sample_method
proc
end
# => :sample_method
If we call this method without a block,
then we’ll get ArgumentError
.
# Method called without a block
sample_method
ArgumentError: tried to create Proc object without a block
We’ll also get ArgumentError
if we use lambda
instead of proc
.
To handle this error, we need to explicitly add block_given?
condition.
Because method doesn’t tell us to pass anonymous block.
# proc in a method
def sample_method
proc if block_given?
end
# => :sample_method
sample_method
#=> nil
That is why, Ruby 2.7 has added warning for Proc.new and proc without block in a method called with a block and errors for lambda without block in a method called with a block.
Before
We do not get any warning when Proc.new and proc is used without block in a method in earlier versions.
# proc without block in a method
def sample_method
proc
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
# => "Hello"
We get a warning when lambda is used without block in a method.
# lambda without block in a method
def sample_method
lambda
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
(irb):11: warning: tried to create Proc object without a block
# => "Hello"
Ruby 2.7
With Ruby 2.7, We will get a warning for Proc.new and proc without block in a method called with a block.
# proc without block in a method
def sample_method
proc
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
(irb):65: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
# => "Hello"
It will give error for lambda without block in a method called with a block.
# lambda without block in a method
def sample_method
lambda
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
ArgumentError (tried to create Proc object without a block)
# proc with block in a method
def sample_method(&block)
proc &block
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
# => "Hello"
# lambda with block in a method
def sample_method(&block)
lambda &block
end
# => :sample_method
# Method called with a block
sample_method { "Hello" }.call
# => "Hello"