From: Patrick Gundlach Date: 2005-12-08T18:07:37+09:00 Subject: Re: increasing counter whithin loop? Hi mental, > Maybe think of it like foreach in TCL [ foreach i $things { ... } ], > or the one for in Javascript [ for (var i in things) { ... } ] > rather than for in C. Hmm, I don't know tcl nor JS well enough. > As a rule, I think Ruby's going to be extremely counterintuitive > whenever you expect C-like behavior. It worked quite well before. > That will probably require thinking about it from a different angle. > The "skip the next (future) element based on the current one" is an > inherently messy concept. Perhaps more messy than a loop without this feature, but a next_and_skip_next_element should be perfectly clear to a reader. I mean, if we have 'complicated' constructs such as 'inject', we will be able to cope with 'skip_next_element', won't we? [...] > prev = nil > a.each do |elt| > puts elt unless prev == "b" > prev = elt > end > > Now, we'll imagine for the moment that Ruby has C-like for loops: > > a = %w(a b c d e) > > for ( i = 0 ; i < a.size ; i += 1 ) > puts a[i] > i += 1 if a[i] == "b" > end You know that those are not the same. The first one is looking back, the second could look forward. > Out of curiousity, do you think either of these would be clearer? > > a.each_with_prev do |elt, prev| > next if prev == "b" > puts elt > end Definitely, but one can do this already with inject. Well, almost. > A lot of Ruby's clarity comes not from being able to write things > clearly in the "raw" language, but from being able to easily > customize the language for your needs. Of course, and that is what I am asking in the whole thread! Is there a nicer way for this loop... Let's see. I have this each_with_next now, but still I am completely unstatisfied with my loop. But I am now convinced that I have the optimal solution, even if it the way it looks now. And btw., I need a look-ahead for this specific purpose. The each_with_previous was a very nice hint, thanks, even if I wasn't able to use it. I'd probably have to create each_with_prev_and_next. module Enumerable def each_with_next(last=nil) prev=nil first=true each do |elt| begin if first first=false next else yield prev,elt end ensure # in case of 'next' prev = elt end end yield prev,last end end a=[:a, :b, :b, :c, :b, :d, :e] skip=false a.each_with_next do |elt,n| if skip skip=false next end if elt==:b && n==:b puts "double_b" skip=true else puts elt end end Patrick (please, no cc:)