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.
Brian A.
On Oct 25, 2007, at 6:40 PM, Brian A. wrote:
end
3.times do |i|
print '2nd or more: ’ unless i.zero?
puts “iteration: #{i}”
end
Gary W.
On Oct 25, 2007, at 6:40 PM, Brian A. wrote:
end
initialized twice, so I expect some initialization outside the loop is
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
On Oct 25, 6:50 pm, Gary W. [email protected] wrote:
end
…
end
3.times do |i|
print '2nd or more: ’ unless i.zero?
puts “iteration: #{i}”
end
I guess I wasn’t clear enough. This should work in any type of
iteration, so a loop index may not be available. For example:
foo.each do |bar|
skip_first { … }
…
end
On Oct 25, 7:18 pm, Morton G. [email protected] wrote:
else
end
ever needing ‘n’ to be other than 1, but it feels strange to not
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.
What I’m trying to accomplish is a convenient way to execute a block
of code on every iteration except the first (or only on the first
iteration).
For some reason you are ignoring that Integer#times passes an index
into its block,
Yes, that’s because a loop index will not always be available. The
times example was just an example. Consider:
foo.each do |bar|
skip_first { … }
…
end
On Oct 25, 2007, at 4:40 PM, Brian A. wrote:
first = true
3.times do
if first
first = false
else
puts ‘foo’
end
…
end
as others have mentioned you can use the block counter that’s passed
- but in general i’ve done things like this before:
cfp:~ > cat a.rb
block = lambda{ block = lambda{ puts ‘foo’ } }
3.times{ block.call }
cfp:~ > ruby a.rb
foo
foo
which, of course, can work for things like #each too.
a @ http://codeforpeople.com/
On 10/26/07, Brian A. [email protected] wrote:
end
I’d like to be able to do the following instead:
3.times do
skip_first { puts ‘foo’ }
…
end
arr = %w[foo bar bat foo]
arr[1…-1].each do |x|
p x
end
puts
OR
arr.each_with_index do |x,i|
p x if i !=0
end
If these are no good, then I am not understanding your question.
Harry
Brian A. wrote:
end
initialized twice, so I expect some initialization outside the loop is
necessary.
So, what’s the most elegant way to solve this?
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
On 10/26/07, Brian A. [email protected] wrote:
What I’m trying to accomplish is a convenient way to execute a block
of code on every iteration except the first (or only on the first
iteration).
I haven’t figured out a way to avoid initializing outside the loop, but
is
this the kind of functionality you’re after?
def skipn(n)
x = -1
proc {|block|
if (x += 1) == n
block.call
true
else
false
end
}
end
skip = skipn(1) # or 0 or 2 or …
(‘a’…‘d’).each do |i|
next if skip[ proc { puts “Hi” } ]
puts i
end
skip = skipn(1)
(‘a’…‘d’).each do |i|
break if skip[ proc { puts “Hi” } ]
puts i
end
END
a
Hi
c
d
a
Hi
Regards,
Sean
On Oct 25, 2007, at 7:35 PM, ara.t.howard wrote:
foo
Whoa! That’s pretty intense! Can you please explain how that works?
I’m totally lost to your magic.
Ari
--------------------------------------------|
If you’re not living on the edge,
then you’re just wasting space.
On Oct 25, 2007, at 8:28 PM, mortee wrote:
5.times &skip_first {|a| puts a}
that makes for a quite interesting syntax option if you chained a few
levels deep too:
foo &a &b &c { bar }
interesting stuff!
a @ http://codeforpeople.com/
On Oct 25, 2007, at 9:56 PM, Ari B. wrote:
cfp:~ > ruby a.rb
foo
foo
Whoa! That’s pretty intense! Can you please explain how that works?
I’m totally lost to your magic.
It changes what the local variable block holds on the first call. So
basically, the first call is the warm-up call that builds a function
to handle all future calls which do the real work.
James Edward G. II
On Oct 25, 2007, at 7:30 PM, Brian A. wrote:
first = false
…
Here are a couple I’ve come up with minus some implementation
skip_first.run { puts ‘hi’ }
I experimented with using a binding, but I discovered that a new
of code on every iteration except the first (or only on the first
…
end
Well, I’m pretty simple minded, so I would use a simple class to
solve this problem. Something like
class Skipper
def initialize(n)
@n = n
end
def call
yield if (@n -= 1) < 0
end
end
skip_1 = Skipper.new(1)
a = []
4.times { |i| skip_1.call { a << i } }
a # => [1, 2, 3]
skip_2 = Skipper.new(2)
a = []
%w[a b c d].each { |w| skip_2.call { a << w } }
a # => [“c”, “d”]
But it would appear you’ve already rejected that kind of solution.
Why don’t you like it?
Regards, Morton
From: news [mailto:[email protected]] On Behalf Of mortee
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
now that is cool 
kind regards -botp
2007/10/26, Brian A. [email protected]:
puts 'foo'
iteration, so a loop index may not be available. For example:
foo.each do |bar|
skip_first { … }
…
end
Of course there is also a solution with #inject. It can be abused when
using this form:
foo.inject do |junk,x|
puts x
end

Other than that you could do
module Enumerable
def skip(n,&b)
raise ArgumentError, “invalid skip count” if n<0
each_with_index {|a,i| b[a] if i>=n}
end
end
This could be extended to skip the last n elements if n is negative
but this is more complex.
Kind regards
robert
Peña wrote:
# using the & notation
5.times &skip_first {|a| puts a}
1
2
3
4
now that is cool 
kind regards -botp
Thx (:
In the meantime I just realized that the binding of the block which does
the real work (the innermost one) is distinct from the one which does
the counting, so using cryptic variable names trying to avoid name
collisions isn’t even needed.
mortee
On Oct 25, 6:38 pm, Brian A. [email protected] wrote:
Consider the following code:
…
Thanks for all the feedback. My apologies for confusing many people
with my choice of an example. This should work for any type of
iteration “n.times”, “while true”, “foo.each”, etc., and I don’t want
to skip processing the first element of a collection.
Here’s the specific example that motivated the question with my
current solution, hopefully it will clarify some things.
class SkipN
def initialize n
@n = n
end
def run
if @n < 1
yield
else
@n -= 1
end
end
def self.skip_first
return new(1)
end
end
skip_first = SkipN.skip_first
ARGV.each do |domain|
skip_first.run { sleep 10 }
available = whois #{domain}
=~ /No match for “#{domain.upcase}”./
puts “#{domain} is #{available ? ‘’ : ‘NOT’} available”
end
I think it’s much clearer to have the block defined within the loop
than to create a lambda outside the loop because this is a replacement
for the following code that would normally be in the loop:
if first
first = false
else
do some processing
end
Originally, I simply placed the sleep at the end of the loop, but I
didn’t like the unnecessary sleep on the last iteration.
Brian A.
On Oct 25, 2007, at 11:03 PM, James Edward G. II wrote:
Whoa! That’s pretty intense! Can you please explain how that
works? I’m totally lost to your magic.
It changes what the local variable block holds on the first call.
So basically, the first call is the warm-up call that builds a
function to handle all future calls which do the real work.
James Edward G. II
Hm. I didn’t know blocks could do that!
So if you wanted to skip the first two, you’d do:
block = lambda{ block = lambda{ block = lambda{ puts ‘foo’ } } }
This easily goes on the 1337 wall of 1337. Have never seen something
like this!
-------------------------------------------------------|
~ Ari
crap my sig won’t fit
On Oct 25, 11:24 pm, Morton G. [email protected] wrote:
3.times do
3.times do
So, what’s the most elegant way to solve this?
skip_first = SkipN.new(1)
end
foo.each do |bar|
@n = n
skip_2 = Skipper.new(2)
a = []
%w[a b c d].each { |w| skip_2.call { a << w } }
a # => [“c”, “d”]
But it would appear you’ve already rejected that kind of solution.
Why don’t you like it?
I think it’s the least objectionable at this point
It’s just not as
nice as:
skip_first { foo }
On Oct 25, 7:35 pm, “ara.t.howard” [email protected] wrote:
end
as others have mentioned you can use the block counter that’s passed
- but in general i’ve done things like this before:
cfp:~ > cat a.rb
block = lambda{ block = lambda{ puts ‘foo’ } }
3.times{ block.call }
Clever
I’ve used a similar technique in JavaScript, but I don’t
like defining the code outside of the loop, and it’s also not as clear
as other solutions IMO.