From: Jason Voegele Date: 2002-02-22T05:19:25+09:00 Subject: Re: Help with blocks? > I'm trying to learn Ruby; just started. I like what I've understood > very much, but I've hit the concept of blocks and bounced. :-( I've > read the reference manual, and Andy and Dave's book, but I still can't > seem to grasp what blocks are about. My main difficulty seems to be > telling the difference between when and how a block is defined, and > when and how it's used. I'm not even sure that 'defined' and 'used' are > appropriate concepts. Can anyone explain this to me in words >simple enough for a C++ programmer to understand? ;-) TIA. The nearest concept in C++ is the function pointer (or perhaps "function objects" or "functors"...haven't kept up with C++ lately). In essence, blocks represent a form of deferred execution. When you create a block (i.e. put some code in { ... } or do ... end) you are defining what the block will do when it is called. Usually, blocks in Ruby are tied to a method invocation, meaning that when you call a method and follow the method call with a block, you expect the method you are calling to "call back" to your block. For example: array.each { |element| puts("#{element}") } Here, you are calling the "each" method of an array, and passing it a block (the stuff between the { and }), expecting the each method to call back to your block once for each element of the array. This is accomplished by the each method using a "yield" statement for each element in the array. "yield" transfers control to the block associated with a particular method invocation. In C++ terms, you'd have something like the following (forgive any errors please ;-) void myblock(void* element) { cout << *element << endl; } // assume there's an each method for arrays that takes a function pointer myarray.each(myblock); (Someone who's current with C++ can probably give a better example using the STL). The added advantage of Ruby blocks is that (when they are bound to a Proc object) they are lexical closures. This means that the "bundle up" their surrounding environment (particularly variables accessed within the block) and carry it around with them so that you can pass the block around anywhere and it still has access to its environment. For example: class Person def initialize(name) @name = name end def create_proc proc { puts @name } end end me = Person.new("Jason Voegele") myproc = me.create_proc myproc.call # => prints "Jason Voegele" By the time you call the block associated with "myproc", the @name variable is no longer in scope. But since Proc objects are closures, the @name variable has been "bundled" with the proc object and remains accessible to the block regardless of where you pass it around and call it. Hope this helps. Jason Voegele