From: mortee Date: 2007-10-26T23:49:28+09:00 Subject: Re: Skip the first invocation e.g. skip_first { foo } Brian Adkins wrote: > On Oct 25, 10:28 pm, mortee 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. 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