# 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