Question on blocks and iterators

hello

at the end is a sample code
this does not work as I want. I want to use each_if
to yield only the elements that support a certain criteria and then
do something with this elements. but
here the output is:

…/bl.rb
e: 5
e: 8
e: 9
2
4
5
8
9

I do not want the numbers 2 and 4 to be printed

I could save the elements in an array and return it but I was wondering if
there is another possibility

Markus

class Array

def each_if(&b)
    each do |e|
        if b.call(e)
            print "e: ", e, "\n"
            yield e
        end
    end
end

end

a = [2, 4, 5, 8, 9]

a.each_if { |x| x > 4 }.each { |e| puts e }

hello

at the end is a sample code
this does not work as I want. I want to use each_if
to yield only the elements that support a certain criteria and then
do something with this elements. but
here the output is:

…/bl.rb
e: 5
e: 8
e: 9
2
4
5
8
9

I do not want the numbers 2 and 4 to be printed

I could save the elements in an array and return it but I was wondering if
there is another possibility

A couple of minor changes (see comments) and this works:

class Array

def each_if(b)             # no &
    each do |e|
        if b.call(e)
            print "e: ", e, "\n"
            yield e
        end
    end
end

end

a = [2, 4, 5, 8, 9]

a.each_if(proc { |x| x > 4 }) { |e| puts e }

one block above is passed as a param

But you could also simply do

a.select {|x| x>4 }.each {|e| puts e}

Couldn’t you? The print is just for debugging, right?

Hal

···

----- Original Message -----
From: “Markus Jais” info@mjais.de
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, June 18, 2003 6:18 PM
Subject: question on blocks and iterators

Markus Jais info@mjais.de wrote in message news:bcqr0s$m8dq4$1@ID-75083.news.dfncis.de

hello

at the end is a sample code
this does not work as I want. I want to use each_if
to yield only the elements that support a certain criteria and then
do something with this elements. but
here the output is:

./bl.rb
e: 5
e: 8
e: 9
2
4
5
8
9

I do not want the numbers 2 and 4 to be printed

I could save the elements in an array and return it but I was wondering if
there is another possibility

Markus

class Array

def each_if(&b)
    each do |e|
        if b.call(e)
            print "e: ", e, "\n"
            yield e
        end
    end
end

end

a = [2, 4, 5, 8, 9]

a.each_if { |x| x > 4 }.each { |e| puts e }

Just some comments to explain the result you obtain :
the each method returns always the calling object, so your each_if returns also
the calling object

a.each_if{ |x| x > 4 }.each { |e| puts e }
is same as
a.each { |e| puts e }

Thats why you get all the numbers printed out.

Concerning the proc’s that are passed to a method:
def each_if(&b)

end

means that ‘b.call’ is the same as ‘yield’. In your case you need two procs
so you have to pass one explicitely in a parameter (without &).

Ciao

hello

at the end is a sample code
this does not work as I want. I want to use each_if
to yield only the elements that support a certain criteria and then
do something with this elements. but
here the output is:

…/bl.rb
e: 5
e: 8
e: 9
2
4
5
8
9

I do not want the numbers 2 and 4 to be printed

I could save the elements in an array and return it but I was wondering
if
there is another possibility

A couple of minor changes (see comments) and this works:

class Array

def each_if(b) # no &
each do |e|
if b.call(e)
print "e: ", e, “\n”
yield e
end
end
end

end

a = [2, 4, 5, 8, 9]

a.each_if(proc { |x| x > 4 }) { |e| puts e }

one block above is passed as a param

But you could also simply do

a.select {|x| x>4 }.each {|e| puts e}

Couldn’t you? The print is just for debugging, right?

Hal

thanks. that works fine. the print was just for debugging. I will use this
for something else than the array class but the example was easier.

just for my understanding:
what is the difference between using “proc” as in your example and using “&”
in the method definition like "def each_if(&b)

one thing I found is that the “&b” solution does not work because of syntax
reasons.

…/bl.rb:20: syntax error
a.each_if { |x| x > 4 } { |e| puts e }

are there any other differences ??
according to the documentation both create a Proc object.

Markus

class Array

def each_if(b) # no &
each do |e|
if b.call(e)
print "e: ", e, “\n”
yield e
end
end
end

end

thanks. that works fine. the print was just for debugging. I will use this
for something else than the array class but the example was easier.

just for my understanding:
what is the difference between using “proc” as in your example and using “&”
in the method definition like "def each_if(&b)

& reifies the “implicit block”, that is, the one passed as in
somemethod { |x| foo(x) }

In your method, you needed 2 blocks:

  • the condition
  • the code the be executed in case the condition is true

In your first code, IIRC something like
def each_if(&b)
each do |e|
if b.call(e)
print "e: ", e, “\n”
yield e
end
end
end
both b.call and yield would execute the “implicit” block (code on
match), not the condition. That’s why, as you need 2 different blocks,
one of them has to be passed explicitly as a Proc.

one thing I found is that the “&b” solution does not work because of syntax
reasons.

…/bl.rb:20: syntax error
a.each_if { |x| x > 4 } { |e| puts e }

I guess you were trying to do
def each_if(&condition, &block)
each {|e| block[e] if condition[e]}
end

but this won’t work because you can only pass one block to the function,
if you need more they have to be converted by hand to Proc with
Kernel.proc and then passed as normal parameters.

are there any other differences ??
according to the documentation both create a Proc object.

If no block is passed to
def foo(&block)
end

block.call(bla) will fail w/ NameError (undefined method `call’ for nil)
whereas yield will raise a LocalJumpError (no block given).

···

On Thu, Jun 19, 2003 at 04:59:32PM +0900, Markus Jais wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Turn right here. No! NO! The OTHER right!