break from block

F

Farrel Lifson

I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

Farrel
 
H

hemant

I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

Farrel

I am not sure about the solution, but the reason of the error is not
that break is not valid within in Procs!!

Try return in place of break and you will still get the error.
Something else is going on here that needs explanation.
 
F

Farrel Lifson

I'm not sure it's the Ruby way (I'm too new to Ruby to judge) but how
about:

block = lambda{|i| i > 5 ? throw:)enough) : nil}
n = 10

catch:)enough) do
n.times &block
end

I tried that but it's a performance killer (nearly 3 times as slow in
my informal testing), which I'm trying to optimise for atm.

Farrel
 
R

Robert Klemme

I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

The direct form works.

irb(main):008:0> 10.times {|i| p i; break if i > 5}
0
1
2
3
4
5
6
=> nil

Hm, at the moment I do not have an idea. What do you need that for?
Maybe there is a different solution. For example:

irb(main):009:0> crit = lambda {|i| i > 5}
=> #<Proc:0x00395698@(irb):9>
irb(main):010:0> 10.times {|i| p i; break if crit}
0
1
2
3
4
5
6
=> nil

Cheers

robert
 
H

hemant

I tried that but it's a performance killer (nearly 3 times as slow in
my informal testing), which I'm trying to optimise for atm.

Farrel

I think i got the error Farrel:

http://www.ruby-doc.org/core/classes/LocalJumpError.html

when you call 10.times {|i| break if i>5; p i}, it works because its
not the one object that is being passed around, but when you pass pass
a proc object to as an block to the method call, its initialized only
once and once you do a break from the proc, subsequent calls fail
because of LocalJumpError, because proc was terminated by :break( and
will get terminated by :redo, :retry, :next, :return, or :noreason.)
 
F

Farrel Lifson

I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

The direct form works.

irb(main):008:0> 10.times {|i| p i; break if i > 5}
0
1
2
3
4
5
6
=> nil

Hm, at the moment I do not have an idea. What do you need that for?
Maybe there is a different solution. For example:

irb(main):009:0> crit = lambda {|i| i > 5}
=> #<Proc:0x00395698@(irb):9>
irb(main):010:0> 10.times {|i| p i; break if crit}
0
1
2
3
4
5
6
=> nil

Cheers

robert


I'm just trying to optimise some code and I was wondering if doing
block = lambda{|i| #processing; if i > 5; break}
n.times &block
would be any faster than doing it directly.

Farrel
 
C

Christopher Brown

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

The direct form works.

irb(main):008:0> 10.times {|i| p i; break if i > 5}
0
1
2
3
4
5
6
=> nil

Hm, at the moment I do not have an idea. What do you need that for?
Maybe there is a different solution. For example:

irb(main):009:0> crit = lambda {|i| i > 5}
=> #<Proc:0x00395698@(irb):9>
irb(main):010:0> 10.times {|i| p i; break if crit}
0
1
2
3
4
5
6
=> nil

Cheers

robert


I'm just trying to optimise some code and I was wondering if doing
block = lambda{|i| #processing; if i > 5; break}
n.times &block
would be any faster than doing it directly.

Farrel

On a tangential note, I'd be worried about the not-so-obvious flow
control.
Why not make the block a boolean predicate and do all the flow
control from inside the loop?

irb(main):022:0> 10.times do |i|
irb(main):023:1* break unless block.call i
irb(main):024:1> p i
irb(main):025:1> end

Now the flow control is based on evaluation obvious to the looping
construct and the contract for the block is "returns boolean".
If the block alters the flow control, it's much less clear. In the
case above, you know when "p i" is going to be skipped. If the block
breaks, it's not clear.

Cheers,
Chris

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (Darwin)

iD8DBQFFOOynrOGxDZoCCzURApcyAKDrtZIjBzxMXGQDzbGy29O0QpvxCwCgytLK
SaG82KxwSV3lIz+iDP8LPq0=
=7ItU
-----END PGP SIGNATURE-----
 
R

Robert Klemme

I'm just trying to optimise some code and I was wondering if doing
block = lambda{|i| #processing; if i > 5; break}
n.times &block
would be any faster than doing it directly.

I do not know a single case where the lambda variant is faster than the
direct block variant. AFAIK that's because of the conversion that
occurs. The advantage of the lambda variant is rather that you can
store the block away and reuse it multiple times.

Regards

robert
 
F

Farrel Lifson

I do not know a single case where the lambda variant is faster than the
direct block variant. AFAIK that's because of the conversion that
occurs. The advantage of the lambda variant is rather that you can
store the block away and reuse it multiple times.

Regards

robert

From my informal benchmarking there's a very slight constant speedup
of about 1s for my program.

Farrel
 
A

ara.t.howard

of about 1s for my program.

what version are you running? your original code works fine here:

harp:~ > cat a.rb
block = lambda{|i| p i; i > 5 ? break : nil}
42.times &block


harp:~ > ruby a.rb
0
1
2
3
4
5
6

harp:~ > ruby --version
ruby 1.8.4 (2005-12-01) [i686-linux]

harp:~ > uname -srm
Linux 2.4.21-47.EL i686

harp:~ > cat /etc/redhat-release
Red Hat Enterprise Linux WS release 3 (Taroon Update 8)

can you show an actual error?

-a
 
F

Farrel Lifson

of about 1s for my program.

what version are you running? your original code works fine here:

harp:~ > cat a.rb
block = lambda{|i| p i; i > 5 ? break : nil}
42.times &block


harp:~ > ruby a.rb
0
1
2
3
4
5
6

harp:~ > ruby --version
ruby 1.8.4 (2005-12-01) [i686-linux]

harp:~ > uname -srm
Linux 2.4.21-47.EL i686

harp:~ > cat /etc/redhat-release
Red Hat Enterprise Linux WS release 3 (Taroon Update 8)

can you show an actual error?

-a

irb(main):001:0> block = lambda{|i| p i; i > 5 ? break : nil}
=> #<Proc:0xb7a9b8f4@(irb):1>
irb(main):002:0> 42.times &block
0
1
2
3
4
5
6
LocalJumpError: break from proc-closure
from (irb):1:in `times'
from (irb):2

farrel@nicodemus ~ $ ruby --version
ruby 1.8.5 (2006-08-25) [i686-linux]

I had the same results on my windows 2000 box at work (which is running 1.8.4).

Farrel
 
M

matt neuburg

Farrel Lifson said:
I've just run into the following problem. Doing this:
block = lambda{|i| i > 5 ? break : nil}
n.times &block
raises a LocalJumpError, I assume because break is not valid from
within a Proc object. Is there any way to get around this?

block = lambda{|i| p i; i > 5 ? throw:)done) : nil}
catch:)done) {42.times &block}

m.
 
H

hemant

of about 1s for my program.

what version are you running? your original code works fine here:

harp:~ > cat a.rb
block = lambda{|i| p i; i > 5 ? break : nil}
42.times &block


harp:~ > ruby a.rb
0
1
2
3
4
5
6

harp:~ > ruby --version
ruby 1.8.4 (2005-12-01) [i686-linux]

harp:~ > uname -srm
Linux 2.4.21-47.EL i686

harp:~ > cat /etc/redhat-release
Red Hat Enterprise Linux WS release 3 (Taroon Update 8)

can you show an actual error?

This is wierd , i got the same error here:

uname -a
Linux webfront 2.6.15-23-server #1 SMP Tue May 23 15:10:35 UTC 2006
i686 GNU/Linux

ruby -v
ruby 1.8.4 (2005-12-24) [i486-linux]

Dapper

How, come you are not getting the error?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,142
Messages
2,570,819
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top