[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

break from block

Farrel Lifson

10/20/2006 1:46:00 PM

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

13 Answers

hemant

10/20/2006 2:20:00 PM

0

On 10/20/06, Farrel Lifson <farrel.lifson@gmail.com> 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.


--
There was only one Road; that it was like a great river: its springs
were at every doorstep, and every path was its tributary.

Farrel Lifson

10/20/2006 2:23:00 PM

0

On 20/10/06, Michael Studman <me@michaelstudman.com> wrote:
> 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'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

Robert Klemme

10/20/2006 2:28:00 PM

0

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

Cheers

robert

hemant

10/20/2006 2:33:00 PM

0

On 10/20/06, Farrel Lifson <farrel.lifson@gmail.com> wrote:
> On 20/10/06, Michael Studman <me@michaelstudman.com> wrote:
> > 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'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
>
>

I think i got the error Farrel:

http://www.ruby-doc.org/core/classes/LocalJump...

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

--
There was only one Road; that it was like a great river: its springs
were at every doorstep, and every path was its tributary.

Farrel Lifson

10/20/2006 2:37:00 PM

0

On 20/10/06, Robert Klemme <shortcutter@googlemail.com> wrote:
> On 20.10.2006 15:45, Farrel Lifson 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@(irb):9>
> irb(main):010:0> 10.times {|i| p i; break if crit[i]}
> 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

Christopher Brown

10/20/2006 3:35:00 PM

0

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


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

> On 20/10/06, Robert Klemme <shortcutter@googlemail.com> wrote:
>> On 20.10.2006 15:45, Farrel Lifson 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@(irb):9>
>> irb(main):010:0> 10.times {|i| p i; break if crit[i]}
>> 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-----

Robert Klemme

10/20/2006 4:05:00 PM

0

On 20.10.2006 16:37, Farrel Lifson 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


Farrel Lifson

10/20/2006 10:47:00 PM

0

On 20/10/06, Robert Klemme <shortcutter@googlemail.com> wrote:
> On 20.10.2006 16:37, Farrel Lifson 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

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

Farrel

Ara.T.Howard

10/21/2006 4:41:00 AM

0

Farrel Lifson

10/21/2006 9:51:00 AM

0

On 21/10/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
> On Sat, 21 Oct 2006, Farrel Lifson wrote:
>
> > On 20/10/06, Robert Klemme <shortcutter@googlemail.com> wrote:
> >> On 20.10.2006 16:37, Farrel Lifson 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
> >
> >> 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
> --
> 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@(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