Forum: Ruby break statement in Loop

5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-18 08:25
a=[[1,2,3],[2,3,4],[54,6,5]]

for i in a
  for j in i
    puts j
    if j.eql?2
      break
    end
  end
end

This break breaks the inner loop, but I would like to get out of the
both loop once condition is reached. Can I do this without using flag
kind of thing?

RAJ
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-02-18 08:49
Raja gopalan wrote in post #1136996:
> a=[[1,2,3],[2,3,4],[54,6,5]]

> This break breaks the inner loop, but I would like to get out of the
> both loop once condition is reached. Can I do this without using flag
> kind of thing?

I'd do as below :

a=[[1,2,3],[2,3,4],[54,6,5]]
prc = proc { break }
for i in a
  for j in i
    puts j
    if j.eql?2
      prc.call
    end
  end
end

**output**
1
2
5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-18 08:55
hi Arup Rakshit

It's not working for me,

My output is this

1
2
3
2
3
4
54
6
5

I am using Ruby 1.8.7 that might be cause of this?
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-02-18 09:04
Raja gopalan wrote in post #1136999:
> hi Arup Rakshit
>
> It's not working for me,
>

May be. My version is -


C:\ruby>ruby -v hello.rb
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]
1
2

C:\ruby>
5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-18 09:16
ok Thank you Arup Rakshit
15000f55138ae94b0f362ed7c625461a?d=identicon&s=25 unknown (Guest)
on 2014-02-18 21:46
(Received via mailing list)
Am 18.02.2014 08:25, schrieb Raja gopalan:
> a=[[1,2,3],[2,3,4],[54,6,5]]
>
> for i in a
>   for j in i
>     puts j
>     if j.eql?2
>       break
>     end
>   end
> end

First, I would write this like:

a = [[1,2,3], [2,3,4], [54,6,5]]

a.each do |i|
  i.each do |j|
    puts j
    break  if j == 2
  end
end

(actually, I also wouldn't use one-letter variable names)

> This break breaks the inner loop, but I would like to get out of the
> both loop once condition is reached. Can I do this without using flag
> kind of thing?

Second, you can achieve this by wrapping your code in a method
and using return:


def handle(array)
  array.each do |i|
    i.each do |j|
      puts j
      return  if j == 2
    end
  end
end

a = [[1,2,3], [2,3,4], [54,6,5]]
handle(a)

Output:
1
2


Regards,
Marcus
15000f55138ae94b0f362ed7c625461a?d=identicon&s=25 unknown (Guest)
on 2014-02-18 22:18
(Received via mailing list)
Am 18.02.2014 08:49, schrieb Arup Rakshit:
> prc = proc { break }
> 1
> 2

This is very unclear, and in 1.8 proc behaves differently.

Introducing a method and using return instead of break would be
much clearer (see my other post).

Also possible: throw and catch

a = [[1,2,3], [2,3,4], [54,6,5]]

catch :quit do
  a.each do |i|
    i.each do |j|
      puts j
      throw(:quit)  if j == 2
    end
  end
end


Regards,
Marcus
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-02-18 22:32
unknown wrote in post #1137119:
> Am 18.02.2014 08:49, schrieb Arup Rakshit:
>> prc = proc { break }
>> 1
>> 2
>
> This is very unclear, and in 1.8 proc behaves differently.

Thanks for letting me know.

> Introducing a method and using return instead of break would be
> much clearer (see my other post).

Yes, that was nice. I actually wanted to show OP, how to break out from
the loop.

> Also possible: throw and catch
>
> a = [[1,2,3], [2,3,4], [54,6,5]]
>
> catch :quit do
>   a.each do |i|
>     i.each do |j|
>       puts j
>       throw(:quit)  if j == 2
>     end
>   end
> end

Nice learning for me.

> Regards,
> Marcus
Bee69cfed999cd13e3bff73d472a39ee?d=identicon&s=25 Hassan Schroeder (Guest)
on 2014-02-18 23:01
(Received via mailing list)
On Mon, Feb 17, 2014 at 11:25 PM, Raja gopalan <lists@ruby-forum.com>
wrote:
>
> This break breaks the inner loop, but I would like to get out of the
> both loop once condition is reached. Can I do this without using flag
> kind of thing?

I don't see the point of two loops for this, so how about --

a = [[1,2,3], [2,3,4], [54,6,5]].flatten
( puts (x = a.shift); break if x.eql?(2) ) until a.empty?

FWIW,
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-02-19 11:43
(Received via mailing list)
On Tue, Feb 18, 2014 at 8:25 AM, Raja gopalan <lists@ruby-forum.com>
wrote:
>
> This break breaks the inner loop, but I would like to get out of the
> both loop once condition is reached. Can I do this without using flag
> kind of thing?

You can use catch throw for this:

catch :outer do
  for i in a
    for j in i
      puts j
      if j.eql?2
        throw :outer
      end
    end
  end
end

Cheers

robert
5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-19 12:16
hi Hassan Schroeder,

You code works, but my intention was to have two loops and breaking two
loops when the condition is met. Thank you.

hi Robert Klemme,

Your Code ROCKS!!!, This is what I expected and I am not even aware of
these type of coding 'catch :outer do'. Thank you.

RAJ
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-02-19 12:52
Robert Klemme wrote in post #1137187:
> On Tue, Feb 18, 2014 at 8:25 AM, Raja gopalan <lists@ruby-forum.com>
> wrote:

> catch :outer do
>   for i in a
>     for j in i
>       puts j
>       if j.eql?2
>         throw :outer
>       end
>     end
>   end
> end

+1 for teaching this one to me. :-)
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-02-19 13:02
(Received via mailing list)
On Wed, Feb 19, 2014 at 12:16 PM, Raja gopalan <lists@ruby-forum.com>
wrote:
> hi Hassan Schroeder,
>
> You code works, but my intention was to have two loops and breaking two
> loops when the condition is met. Thank you.
>
> hi Robert Klemme,
>
> Your Code ROCKS!!!, This is what I expected and I am not even aware of
> these type of coding 'catch :outer do'. Thank you.

You're welcome!  You can even use this to transport information:

irb(main):001:0> x = catch(:foo) { throw :foo }
=> nil
irb(main):002:0> x
=> nil
irb(main):003:0> x = catch(:foo) { throw :foo, 123 }
=> 123
irb(main):004:0> x
=> 123

Cheers

robert
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-02-19 13:41
Robert Klemme wrote in post #1137197:

> You're welcome!  You can even use this to transport information:
>
> irb(main):001:0> x = catch(:foo) { throw :foo }
> => nil
> irb(main):002:0> x
> => nil
> irb(main):003:0> x = catch(:foo) { throw :foo, 123 }
> => 123
> irb(main):004:0> x
> => 123

Again I went to the doc link -
http://www.ruby-doc.org/core-2.1.0/Kernel.html#met... . I
understood what happened with above code.

From the doc one line I don't understand - when no **arg** is given,
`catch` assigns a **new unique object** to throw. this is useful for
**nested catch**.

Can you explain this with a example ?
5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-19 13:57
Robert Klemme wrote in post #1137197:
>
> irb(main):001:0> x = catch(:foo) { throw :foo }
> => nil
> irb(main):002:0> x
> => nil
> irb(main):003:0> x = catch(:foo) { throw :foo, 123 }
> => 123
> irb(main):004:0> x
> => 123
>
> Cheers
>
> robert

Ok Thank you.
920f6e4a0fbf997d851455f827a10ebc?d=identicon&s=25 unknown (Guest)
on 2014-02-19 13:59
(Received via mailing list)
In general, it is considered bad practice to use exceptions for flow
control.
Exceptions indicate, and should be used for, cases where something
unexpected happened and you are trying to recover.
I strongly encourage you not to use them in this way.

The have seen several good alternatives to your problem:
        * flatten the array and use one loop
        * make a method and use return




"ruby-talk" <ruby-talk-bounces@ruby-lang.org> wrote on 02/19/2014
07:41:21
AM:
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-02-19 14:19
(Received via mailing list)
On Wed, Feb 19, 2014 at 1:59 PM, <HANSEM1@nationwide.com> wrote:

> In general, it is considered bad practice to use exceptions for flow
> control.
> Exceptions indicate, and should be used for, cases where something
> unexpected happened and you are trying to recover.
>

These are no exceptions. Notice this:

Exceptions: raise...rescue
Flow control: catch...throw


> I strongly encourage you not to use them in this way.
>

In Ruby this was invented intentionally to allow for such kind of _flow
control_. I agree, one should use is sparingly but there are situations
where it comes handy.  Personally I can't remember the last time I used
it
though. :-)


> The have seen several good alternatives to your problem:
>         * flatten the array and use one loop
>         * make a method and use return
>

There's also another one

irb(main):001:0> a=[[1,2,3],[2,3,4],[54,6,5]]
=> [[1, 2, 3], [2, 3, 4], [54, 6, 5]]
irb(main):002:0> a.each {|i| i.each {|j| p j; break if j == 2} or break}
1
2
=> nil

Works also if the element is not found in the first sub array:

irb(main):006:0> a.each {|i| i.each {|j| p j; break if j == 4} or break}
1
2
3
2
3
4
=> nil

You can see that it completely iterates if the condition does not match:

irb(main):007:0> a.each {|i| i.each {|j| p j; break if j == 999} or
break}
1
2
3
2
3
4
54
6
5
=> [[1, 2, 3], [2, 3, 4], [54, 6, 5]]

If we learn more about the problem that is to be solved here we may come
up
with even better solutions.

Cheers

robert
5dfc843f9ecf6fb64b52a35bdce43910?d=identicon&s=25 Raja gopalan (arc)
on 2014-02-19 14:45
hi Robert Klemme,

"a.each {|i| i.each {|j| p j; break if j == 2} or break}"

This is an another interesting code. You really Rock with Ruby CODE!!!
But I don't understand how this 'or break' works? See the inner each
loop returns the enumerator So Is the 'or operation' performed with
enumerator object?

RAJ
09a32175057418748822c587ac08c429?d=identicon&s=25 Abinoam Jr. (abinoampraxedes_m)
on 2014-02-22 04:56
(Received via mailing list)
Dear Arup,

Basically instead of

catch(:foo) { throw :foo }

You can write

catch { |foo| throw foo }

Look again:

catch(:foo) { |arg| p arg; throw arg }
# :foo
# => nil

catch { |arg| p arg; throw arg }
# #<Object:0x000000025ab778>
# => nil

It creates for you (and for free) a unique instance of Object and
yields it to the block.

I couldn't come out with a good code example where this could be useful.
At least we have two stylist way of writing it! ;-)

https://bugs.ruby-lang.org/issues/1618
https://bugs.ruby-lang.org/projects/ruby-trunk/rep...

Best regards,
Abinoam Jr.
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.