From: George Ogata Date: 2002-07-10T22:09:14+09:00 Subject: Re: for ... else ... end Austin Ziegler wrote: > On Wed, 10 Jul 2002 01:52:38 +0900, David Alan Black wrote: >> I still don't see how a code block can have an 'else' clause. >> Wouldn't this make for some awfully bizarre code? > > I can't, either -- which is why I'm asking the questions: > > 1. How would this work in a case where there is no loop, but just a > block? > 2. How would I construct my own each member function to take > advantage of the else (and possibly other clauses)? > Instead of passing one block with 'else' or 'on_exit' clauses in it, I think you'd have to pass multiple blocks in: one normal block, one "else" block, one "on_exit" block, etc. Currently, the only way to do that is by throwing some Procs in with the args, right? How 'bout a more general construct which makes passing in multiple blocks less messy: arr.each do |el| # stuff block :on_abort do |*args| # stuff block :on_exit do |*args| # stuff #etc. end where `block' is a keyword used to separate/name blocks. Inside the method, you'd invoke the named blocks by their name (the anonymous block at the top, if present, would still be invoked with `yield'): class Array def each if empty? yield_named :on_empty if block_given?(:on_empty) else if catch :broken # see [1] if block_given? (0...length).each do |i| yield self[i] # anonymous block end end yield_named :on_exit if block_given?(:on_exit) false end yield_named(:broken) if block_given?(:broken) end end end end [1] How do you detect if the block was broken? I pretend here `break' == `throw :broken, true'. Or with multiple anonymous blocks: def foo yield_anon 0 if anon_blocks.length > 0 yield_anon 1 if anon_blocks.length > 1 end foo do # anonymous block 1 block do # anonymous block 2 end Using symbols for block names implies you could also use arbitrary objects as block names. The blocks passed could be accessed as a Hash if you want to act on blocks based on their names. Contrived e.g.: class HtmlParser def each_tag blocknames = block_hash.keys @html.scan /<(.*?)>/m do # inadequate regex, but for e.g. blocknames.each do |re| if re =~ $1 yield_named block_hash[re], $~ break end end end end end Yes, I know there are plenty of clean ways to do that HtmlParser example using current Ruby. No, I don't know if there exists any scenarios where any of this would be a _real_ advantage. I'm just throwing another crazy, probably stupid, possibly flawed idea in the air for people to play with/dismiss.