Re: increasing counter whithin loop?



Quoting Patrick Gundlach <clr9.10.randomuser@xxxxxxxxxxxxxxx>:

> 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


.



Relevant Pages

  • Re: increasing counter whithin loop?
    ... > prev = nil ... > prev = elt ... a nicer way for this loop... ...
    (comp.lang.ruby)
  • Re: processing a sequence
    ... (loop for sublist = (collect-sublist) ... return accum if not element = list.first ... if prev and element < prev ... James still didn?t show his Ruby one-liner that outperforms the Lisp ...
    (comp.lang.lisp)
  • Idiomatic lisp - loops
    ... (defun kv-insert (list elt) ... (let* ((h (car list)) ... (setq acc (append (reverse list) ... loop iteration. ...
    (comp.lang.lisp)
  • Re: increasing counter whithin loop?
    ... confine their effects to the block, ... prev = nil ... prev = elt ... > output next to each other, so I wrap them in a 'Group of two ListOfMembers' ...
    (comp.lang.ruby)
  • Re: Iterating over generic sequences.
    ... Using ELT with LOOP or DOTIMES (which seems needlessly inefficient, ... especially for lists). ... (defun do-stuff-with-sequence (sequence) ...
    (comp.lang.lisp)