From: mental@... Date: 2005-12-08T10:14:11+09:00 Subject: Re: increasing counter whithin loop? Quoting Patrick Gundlach : > OK, then it makes sense that one cannot manipulate counter. But > IMO it is not intuitive (POLS ;-)) that the counter in the > for-loop can't be changed. 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. As a rule, I think Ruby's going to be extremely counterintuitive whenever you expect C-like behavior. > Yes, sure, but now it is getting ugly again. I am not looking for > any way to work, but to find a readable, beautiful and ruby-like > piece of code. 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. Notching up the counter in a C-style loop is a _concise_ way to do that, but it's still not particularly easy to reason about if your loop is nontrivial. It seems like the cleaner and more Ruby-esque solutions offered so far involve attacking it from the other end -- "skip the current element based on the previous one". It's clearer to remember things from the past than it is to reach forward into the future. Along those lines (this is basically Trans' suggestion): a = %w(a b c d e) 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 I don't know. I'm not sure I would find the C version clearer if I weren't a grizzled old C veteran. 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 or a.each_with_prev do |elt, prev| puts elt unless prev == "b" end Don't forget that you're allowed to define convenience methods if that would clarify things elsewhere: module Enumerable def each_with_prev( initial=nil ) prev = initial each do |elt| begin yield elt, prev ensure # in case of 'next' prev = elt end end end end 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. -mental