Download this source
# This is a method, with a block parameter.
def other_method(a, &b)
b.call(a)
end
# Call the block method
other_method("Copeco") { | a | puts "Hello there #{a}" }
other_method(28) { | a | puts a * 10 }
# Ruby blocks are true closures - they capture the scope they're defined in.
multiplier = 20
other_method(5) { | a | puts a * multiplier }
# As well as passing blocks in a method call, we can also predef a closure
# with 'lambda', which makes an instance of Proc. You may also see 'proc'
# referred to (as a method) but you should probably prefer the 'lambda' keyword.
square = lambda { | i | puts i * i }
# You must use & to pass predefined, since the method actually expects only
# one arg (the &block argument isn't counted - it means 'the block that's
# attached to the call').
other_method(10,&square)
# So blocks are used to implement coroutines, where a method and block defined
# separately work together for a common goal. This is how a lot of the Ruby API
# (things like each_whatever, inject, etc, etc, etc) is done.
# Much of the time, if you're just going to be calling the block, you don't
# need to bother with a &argument - you can just call 'yield' to pass control
# to the block supplied to the method.
def block_method(text)
yield ">>>" + text + "<<<" if text != nil
yield ">>>" + text + "<<<" if text != nil
end
# So it's basically the same as the closure blocks, except that the
# block argument is implied. The arguments to 'yield' are passed to the block.
# You may need to check if you're given a block, which can be done with:
def careful_block_method
if block_given?
yield self
else
puts "Where's the block?"
end
end
# The following call will print >>>Hello<<< twice.
block_method("Hello") { | it | puts it }
# Does nothing
careful_block_method
Running this outputs:
Hello there Copeco
280
100
100
>>>Hello<<<
>>>Hello<<<
Where's the block?

