Forum: Ruby break from block

05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-20 15:46
(Received via mailing list)
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
A1bd38c7a0c3026842de9c87089bc7fb?d=identicon&s=25 Michael Studman (Guest)
on 2006-10-20 16:14
(Received via mailing list)
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
87e41d0d468ad56a3b07d9a6482fd6d5?d=identicon&s=25 Hemant Kumar (gnufied)
on 2006-10-20 16:22
(Received via mailing list)
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.
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-20 16:24
(Received via mailing list)
On 20/10/06, Michael Studman <me@michaelstudman.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 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-10-20 16:31
(Received via mailing list)
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
87e41d0d468ad56a3b07d9a6482fd6d5?d=identicon&s=25 Hemant Kumar (gnufied)
on 2006-10-20 16:35
(Received via mailing list)
On 10/20/06, Farrel Lifson <farrel.lifson@gmail.com> 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.)
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-20 16:38
(Received via mailing list)
On 20/10/06, Robert Klemme <shortcutter@googlemail.com> 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
0a98b50499e6e846f23756b7f4545ad6?d=identicon&s=25 Christopher Brown (Guest)
on 2006-10-20 17:36
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


On 20 Oct 2006, at 4:37 PM, Farrel Lifson 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-----
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-10-20 18:10
(Received via mailing list)
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
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-21 00:47
(Received via mailing list)
On 20/10/06, Robert Klemme <shortcutter@googlemail.com> wrote:
>
> Regards
>
>         robert

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

Farrel
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-10-21 06:42
(Received via mailing list)
On Sat, 21 Oct 2006, Farrel Lifson 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
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-21 11:52
(Received via mailing list)
On 21/10/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> 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@(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
Fbb4d027695dfdf76bf448b15d7e306a?d=identicon&s=25 unknown (Guest)
on 2006-10-21 19:26
(Received via mailing list)
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?

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

m.
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 Farrel Lifson (Guest)
on 2006-10-21 23:24
(Received via mailing list)
On 21/10/06, matt neuburg <matt@tidbits.com> wrote:
>
> m.
>
> --
> matt neuburg, phd = matt@tidbits.com, http://www.tidbits.com/matt/
> 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
87e41d0d468ad56a3b07d9a6482fd6d5?d=identicon&s=25 Hemant Kumar (gnufied)
on 2006-10-22 04:01
(Received via mailing list)
On 10/21/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> 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?
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.