Break from block

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’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

On 10/20/06, Farrel L. [email protected] wrote:

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.

On 20.10.2006 15:45, Farrel L. wrote:

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@:9(irb)
irb(main):010:0> 10.times {|i| p i; break if crit[i]}
0
1
2
3
4
5
6
=> nil

Cheers

robert

On 20/10/06, Michael S. [email protected] wrote:

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

On 10/20/06, Farrel L. [email protected] wrote:

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.)

On 20/10/06, Robert K. [email protected] wrote:

0

=> 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

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

On 20 Oct 2006, at 4:37 PM, Farrel L. wrote:

irb(main):008:0> 10.times {|i| p i; break if i > 5}
Maybe there is a different solution. For example:
6

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

On 20.10.2006 16:37, Farrel L. wrote:

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

On 20/10/06, Robert K. [email protected] wrote:

Regards

    robert

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

Farrel

On 21/10/06, [email protected] [email protected] wrote:

direct block variant. AFAIK that’s because of the conversion that
what version are you running? your original code works fine here:
3
harp:~ > cat /etc/redhat-release
Red Hat Enterprise Linux WS release 3 (Taroon Update 8)

can you show an actual error?

-a

my religion is very simple. my religion is kindness. – the dalai lama

irb(main):001:0> block = lambda{|i| p i; i > 5 ? break : nil}
=> #Proc:0xb7a9b8f4@:1(irb)
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

Farrel L. [email protected] wrote:

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.

On Sat, 21 Oct 2006, Farrel L. wrote:

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.

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

On 10/21/06, [email protected] [email protected] wrote:

direct block variant. AFAIK that’s because of the conversion that
what version are you running? your original code works fine here:
3
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?

On 21/10/06, matt neuburg [email protected] wrote:

m.


matt neuburg, phd = [email protected], Matt Neuburg’s Home Page
Tiger - http://www.takecontrolbooks.com/tiger-customizing.html
AppleScript - http://www.amazon.com/gp/product/0596102119
Read TidBITS! It’s free and smart. http://www.tidbits.com

I’ve tried using throw/catch but it’s a serious performance cost.

Farrel