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()'.