More Ruby blocks
Michael writes more about ruby blocks:
What I have yet to do, however, is find a way to get braces to work with if, while, or other flow-control type statements. For example, the program yes implemented in Ruby:
while true print "y\n" end
To do that with curly braces you need this:
loop { print "y\n" }
But ruby blocks aren't really like C blocks. A C block introduces a new nested lexical scope. For instance:
void my_func() { int a = 5; printf("a: %d\n", a); { int a = 4; printf("a: %d\n", a); } }
Will print:
a: 5 a: 4
The nested 'a' variable has a value of 4, which overrides the outer one of value 5 in the second printf().
Perhaps the best way to think about a ruby block in C terms, is as a function pointer which carries with it a snapshot of its environment. For instance:
class Klass def setupBlock(&a_block) @my_block = a_block end def callBlock() a = 4 @my_block.call() end end obj = Klass.new a = 5 obj.setupBlock() { puts "a: #{a}" } obj.callBlock
Will print
a: 5
Even though the local variable 'a' is set to 4 inside the method callBlock(). This is because the block has taken a snapshot of the top level where 'a' was set to 5. You pass a block to a method by prefixing the arg name with an ampersand:
def setupBlock(&a_block)
The type of the parameter a_block is 'Proc', and you can invoke it with the Proc.call() method, ie '@my_block.call()'.