Skip the first invocation e.g. skip_first { foo }

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 :slight_smile:
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

:slight_smile:

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 :slight_smile:
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 :slight_smile: 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 :slight_smile: 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.