GGarramuno wrote:

>In the above example, by placing the catch where it is, the way I read
>it was that $stdin.getc gets run only once, instead of in each
>iteration (ie. the while condition is not evaluated as it is OUTSIDE
>the catch do/end, just as is the ensure block)?   This is what's
>loosing me.  What's the logic -magic- that makes it all work?
>  
>

"catch" is just a method.  All it does is evaluate the block that you 
attach to it.  If, "inside" of that block (ie, directly, or via methods 
called from within the block), the "throw" method is called (note that 
it is also a method), AND if the symbol passed to the throw method 
matches the one for the given catch method, THEN the catch method 
terminates, returning the (optional) value passed to the throw method.

  catch(:some_symbol) do
     do_something
     do_something_else
     catch(:another_symbol) do
        do_yet_another_thing
        throw :some_symbol
     end
  end

In the above example, the 'throw' passes control back to the outermost 
catch invocation, which terminates.

>Or to put in another way, what if I wanted to have a catch() that is
>inside the first while loop but does not evaluate the condition nor
>runs the ensure block (say, just to backtrace the code like an ugly
>goto command)?  How would that look like?  Or that's just not possible
>(and thus it explains why the above thing always gets interpreted the
>way we intended)?
>  
>

There is no way (that I know of) to 'throw' within a protected region 
(ie, one inside of a 'begin'...'end', with rescue clauses and an ensure 
clause) without executing the associated ensure block.  'catch' is very 
much like a goto, but it makes sure that 'ensure' clauses are all 
executed on its way out.

Hope that helps...kind of.

- Jamis

-- 
Jamis Buck
jgb3 / email.byu.edu

ruby -h | ruby -e 'a=[];readlines.join.scan(/-(.)\[e|Kk(\S*)|le.l(..)e|#!(\S*)/) {|r| a << r.compact.first };puts "\n>#{a.join(%q/ /)}<\n\n"'