Reputation: 195
I am comfortable with the following:
def some_def(foo, &block)
puts "block utilized below"
block.call(foo)
end
def some_other_def(bar)
puts "using yield below"
yield bar
puts "and back into the method"
end
So I have learned to keep blocks (and procs) separate from the yield
keyword.
However, I ran into the following code:
# ./open_file.rb
class File
def self.open(name, mode, &block)
file = new(name, mode)
return file unless block_given?
yield(file)
ensure
file.close
end
end
It seems the parameter &block
does not matter when I implement execute this code in irb:
irb -r ./file.open.rb
and do something like:
File.open('foo.txt','r') {|f| puts f}
Is &block
rendered optional by block_given?
in:
return file unless block_given?
Upvotes: 2
Views: 1244
Reputation: 434635
Generally, you only use the &block
argument if you need to pass the block to another method such as in this made up example:
def m(&block)
some_array.map(&block)
end
or this real version of Enumerable#sum
from Rails:
def sum(identity = nil, &block)
if block_given?
map(&block).sum(identity)
else
sum = identity ? inject(identity, :+) : inject(:+)
sum || identity || 0
end
end
In either case, the block that the method is called with is used with another method call so you need a way to refer to the block (i.e. a name).
So block_given?
/yield
and &block
serve different purposes. Being able to call block_given?
doesn't make &block
redundant and, as in the #sum
implementation above, they can even be used together.
Upvotes: 5
Reputation: 168081
The &block
in the method signature accepts a block, converts it into a proc, and assigns it to a variable named block
. In case a block is not provided, block
is assigned nil
.
Whether to use the argument block
within the method definition does not matter just like it does not matter whether an ordinary method argument bar
is used or not in the following definition:
def foo(bar); end
However, accepting a block as a parameter and not using it is redundant and waste of resource. It may perhaps still make sense to explicitly indicate to a fellow programmer that the method accepts a block.
Using block_given?
is independent of all this. It is independent of whether a block has been accepted as an argument via &
. It refers to the block directly, irrespective of block
.
Upvotes: 1