Brian said:
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.
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.
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.
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.
It could e.g. be extended to accept two blocks: one which skips the
first n iterations, and one wich does not - but this wouldn't be elegant
any more, and also the local variables would be separate in the two blocks.
What you could still perhaps do is trying to tag your calling contexts
as the basis for skipping, and then from inside the loop body try to
refer to it. Like going upwards the calling stack using
Binding.of_caller, and look for a specially named local variable which
is set up by the former facility, and use that as a reference for how
many times your block has been called. Something like:
collection.some_iterator &skip_context do
# this sets up the context with some counter variable
...
skip_first {
# whithin the skip_first method the above mentioned variable isn't
# visible, but it may be sought for using some stack-traversing
# trickery
...
}
...
end
mortee