From: Eric Mahurin Date: 2005-05-12T23:59:26+09:00 Subject: Re: simple object loops and what they return --- "David A. Black" wrote: > Hi -- > > On Thu, 12 May 2005, Eric Mahurin wrote: > > > inject clearly does what is supposed to. I'm not referring > to > > it. I'm referring to the following loops that are similar > to > > plain while/until/loop loops: > > > > enum.each {|o| ...} -> enum or break value > > enum.each_with_index {|o,i| ...} -> enum or break value > > for o in enum; ... end -> enum or break value > > int.times {|i| ...} -> int or break value > > int.downto(stop) {|i| ...} -> int or break value > > int.upto(stop) {|i| ...} -> int or break value > > int.step(stop,step) {|i| ...} -> int or break value > > > > Compare this to the traditional loops: > > > > loop { ... } -> break value > > while ...; ... end -> nil or break value > > until ...; ... end -> nil or break value > > begin ... end while ... -> nil or break value > > begin ... end until ... -> nil or break value > > > > I guess many may not know that break can take a value as an > > argument and make the broken loop return that. I find this > > behavior quite useful except for those loops that return > > something other than nil in the no-break case (the object > loops > > above). > > > > What about the Integer loops above? Anybody using what > those > > return now - the original int? Maybe I could propose just > > those loops. > > I wonder whether some of the non-consensus about the changes > you've > been discussing originates in the difference between loop > constructs > per se, and iterators. I'm thinking it might be because people may not know that break can take a value and it is returned by the loop expression (even the method loops). I actually haven't found this useful (and quite natural after thinking about it) behavior documented. > (loop itself appears to be a method, > though > oddly it does not identify itself as an iterator. But an > infinite > loop can't really "return" anything anyway.) You're right in that will never return the loop exited normally case (with nil) becasue it is infinite, but if you use you can get it to return something: loop{x=rand(20);break(true) if x==7;break(nil) if x==13} > So the non-traditional loops you've listed are basically > method calls > (including 'for', which I believe is just an 'each' wrapper). > I don't > know that this has to be a determinant one way or the other, > but I > realize it's something that I'd semi-perceived but not quite > put my > finger on that separates these things into two pretty > distinct > categories. Even these non-traditional loops (and even if/else and case) could have been implemented as Kernel methods. If they were, you'd have syntax like this: while(proc{}) {} if(proc{},proc{}) {} And in ruby 1.9, the proc keyword isn't needed - sweet. If ruby is pretty efficient at making/using procs, this might be a good idea to make the language even cleaner (the current while/etc would just be a shorthand). Here is an implementation: def while_method(condition=nil,&body) if not body while(condition[]); end elsif not condition while(body[]); end else while(condition[]); body[]; end end end # same as x=0;while x<10; puts(x);x+=1; end x=0;while_method(proc{x<10}) {puts(x);x+=1} # same as x=0;begin puts(x);x+=1 end while x<10 x=0;while_method {puts(x);x+=1;x<10} Yahoo! Mail Stay connected, organized, and protected. Take the tour: http://tour.mail.yahoo.com/mailtour.html