2007/10/26, mortee <mortee.lists / kavemalna.hu>:
> Brian Adkins wrote:
> > On Oct 25, 10:28 pm, mortee <mortee.li... / kavemalna.hu> wrote:
> >> I'd try something along these lines:
> >>
> >> # sets up a binding with a local variable _iteration = 0, and then
> >> # creates a lambda which inherits this binding, and can use the variable
> >> # note that the lambda also inherits any block given to skip_first,
> >> # so it can also yield
> >>
> >> def skip_first(_skip_count = 1)
> >>   _iteration = 0
> >>   lambda do |x|
> >>     yield x if _iteration >= _skip_count
> >>     _iteration += 1
> >>   end
> >> end
> >>
> >> # you can then pass the lambda returned by skip_first to any iterator,
> >> # using the & notation
> >>
> >> 5.times &skip_first {|a| puts a}
> >> 1
> >> 2
> >> 3
> >> 4
> >
> > So how do you pass the "real" block to the iterator then? The main
> > point of the iteration isn't the code that's skipped on the first
> > iteration, but the main body of the iteration. For example:
> >
> > foo.each do |elem|
> >   skip_first do
> >     # processing to be skipped the first time
> >     # through the loop that may or may not use
> >     # elem
> >   end
> >   # other important processing using elem
> > end
>
> Sorry, it wasn't clear to me by this whole thread but this last post
> that you wanted code which doesn't skip elements, as well as code which
> does.

Oh, that eluded me as well.  In that case it's certainly best to just
use #each_with_index and use the index as you said.

> The bad news is that I guess from inside the block passed to the
> iterator, you have no way (at least no nice way) to keep track of the
> iteration count, and make decisions based on it. You either have to call
> each_with_index, and make use of the passed index, but this won't work
> with other iterators.

It does, if you use Enumerator:

17:26:33 ~$ irb -r enumerator
irb(main):001:0> %w{foo bar baz}.to_enum(:each_with_index).
irb(main):002:0* map {|e,i| i % 2 == 0 ? e : :empty}
=> ["foo", :empty, "baz"]
irb(main):003:0>

> You might also try to set up some global variable the first time your
> block is run, and then utilize that. Note that this will get tricky even
> when repeatedly running loops with skipping sections - not to mention
> nested ones.

I would not go down that road either.

> So in any way, you will have to somehow estabilish what is considered
> your "outermost" scope, and do some counting relative to that. (Just
> consider how skipping would work if called from inside a nested loop.
> Will it skip the first n iteration of the outer loop, or the inner one?)
>
> All in all, you'll almost certainly have to set up your skipping and
> non-skipping code blocks while still *outside* the loop itself. This is
> what e.g. the above proposed skip_first method would do, just hiding the
> variable initialization part from the caller.

Frankly, I believe this shows it's all not worth the effort.  Checking
the provided iteration counter is straightforward and easy to read and
understand.

Kind regards

robert