Break statement in Loop

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

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

hi Arup R.

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?

ok Thank you Arup R.

Raja gopalan wrote in post #1136999:

hi Arup R.

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>

Am 18.02.2014 08:49, schrieb Arup R.:

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

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

unknown wrote in post #1137119:

Am 18.02.2014 08:49, schrieb Arup R.:

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

On Tue, Feb 18, 2014 at 8:25 AM, Raja gopalan [email protected]
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

On Mon, Feb 17, 2014 at 11:25 PM, Raja gopalan [email protected]
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,

Robert K. wrote in post #1137187:

On Tue, Feb 18, 2014 at 8:25 AM, Raja gopalan [email protected]
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. :slight_smile:

hi Hassan S.,

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

hi Robert K.,

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

On Wed, Feb 19, 2014 at 12:16 PM, Raja gopalan [email protected]
wrote:

hi Hassan S.,

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

hi Robert K.,

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

Robert K. 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 -
Module: Kernel (Ruby 2.1.0) . 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 ?

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” [email protected] wrote on 02/19/2014
07:41:21
AM:

Robert K. 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.

On Wed, Feb 19, 2014 at 1:59 PM, [email protected] 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. :slight_smile:

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

hi Robert K.,

“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

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! :wink:

https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/23675/diff/

Best regards,
Abinoam Jr.