From: Morton Goldberg Date: 2007-10-26T08:18:28+09:00 Subject: Re: Skip the first invocation e.g. skip_first { foo } On Oct 25, 2007, at 6:40 PM, Brian Adkins wrote: > Consider the following code: > > first = true > 3.times do > if first > first = false > else > puts 'foo' > end > ... > end > > I'd like to be able to do the following instead: > > 3.times do > skip_first { puts 'foo' } > ... > end > > However, I'm pretty sure that's impossible - especially when you > consider running the above code twice would require state to be > initialized twice, so I expect some initialization outside the loop is > necessary. > > So, what's the most elegant way to solve this? > > Here are a couple I've come up with minus some implementation details. > They work, but I'm not very pleased with either one. I don't recall > ever needing 'n' to be other than 1, but it feels strange to not > generalize it. I also realize it's more typical to want to execute > code only on the first loop invocation, but I had the opposite need > when this question arose. > > # Use an object for state > skip_first = SkipN.new(1) > 3.times do > skip_first.run { puts 'hi' } > ... > end > > # Use a closure for state > skip_first = skipn(1) > 3.times do > skip_first.call lambda { puts 'hi' } > ... > end > > I experimented with using a binding, but I discovered that a new > binding is created each time times invokes the block, so apparently > it's not possible to introduce a variable within the lexical scope of > the block for the duration of the 3.times invocations - or I missed > something. It's not entirely clear to me what you are trying to accomplish, so this may way off base. For some reason you are ignoring that Integer#times passes an index into its block, but if are willing to make use of this index, what you propose can be written as 3.times { |i| puts "hi" if i > 0 } Regards, Morton