Idiom wanted: do-while


#1

So I was working on the quiz solution, and
I had some code like this:

b = simulate board,m
while another_turn?(b,m)
b = simulate b,m
end

If I was doing this in C, I’d use a do-while loop instead, to avoid
repeating the line outside the loop:

b = board;
do {
b = simulate(b.m);
}
while ( another_turnta(b,m));

What’s the do-while idiom in ruby?
I ended up with this, but it needs an extra flag variable:

b,taketurn = board,true
while taketurn
b = simulate b,m
taketurn = another_turn?(b,m)
end

Is there a ruby idiom for do-while?

-Adam


#2

On Dec 12, 2005, at 4:34 PM, Adam S. wrote:

repeating the line outside the loop:
b,taketurn = board,true
while taketurn
b = simulate b,m
taketurn = another_turn?(b,m)
end

Is there a ruby idiom for do-while?

I favor:

loop do

… some action …

break unless …
end

Hope that helps.

James Edward G. II


#3

On Tue, Dec 13, 2005 at 07:42:59AM +0900, James Edward G. II wrote:

Is there a ruby idiom for do-while?

I favor:

loop do

… some action …

break unless …
end

[ruby-core:06745]


#4

Adam S. ha scritto:

repeating the line outside the loop:

b = board;
do {
b = simulate(b.m);
}
while ( another_turnta(b,m));

What’s the do-while idiom in ruby?

you could do

begin

end while somecondition

but I seem to recall it is somewhat “deprecated” and you should follow
James’ suggestion


#5

You can also do
irb(main):011:0> begin
irb(main):012:1* puts “Once”
irb(main):013:1> end while nil
Once
=> nil

Which is what I usually do.

  • Andy D.

#6

On Tue, 13 Dec 2005, Adam S. wrote:

repeating the line outside the loop:
b,taketurn = board,true
while taketurn
b = simulate b,m
taketurn = another_turn?(b,m)
end

Is there a ruby idiom for do-while?

harp:~ > cat a.rb
i = 0

(
p i
i += 1
) while i < 3

harp:~ > ruby a.rb
0
1
2

cheers.

-a


#7

On 12/12/05, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

0
1
2

Not quite. That is just a while loop:

( puts “foo” ) while nil
… nil

which is as always, equivalent to:

while nil
puts “foo”
end

If you really need a do while loop it is not hard to use loop to
accomplish what you need. If you want something more complex you could
easily get this to work:

lambda do

end.while { … }

All you would need is something like this:

class Proc
def while
loop do
result = call
return result unless yield
end
end
end

I am sure there is plenty of room for improving this example too.

Brian.


#8

I was certain I had tried that…
But that works exactly the way I want.
Thanks,
-Adam


#9

On Dec 12, 2005, at 6:19 PM, Adam S. wrote:

I was certain I had tried that…
But that works exactly the way I want.

But hopefully you followed the Ruby Core link in this thread and saw
Matz explaining how he would like to remove it from the language so
we shouldn’t be using it. Stick with loop do … end.

James Edward G. II


#10

On Dec 12, 2005, at 7:36 PM, Steve L. wrote:

I do this quite a bit, but it’s not structured programming and is a
little
like a goto. Break can improve readability on small loops, but on
large loops
maintained by multiple people it can become a nightmare.

Which is probably a sign that method calls are needed. Heck, I think
two programmers working on the same loop is a sign of that. :wink:

James Edward G. II


#11

On Monday 12 December 2005 05:42 pm, James Edward G. II wrote:

Is there a ruby idiom for do-while?

I favor:

loop do

… some action …

break unless …
end

I do this quite a bit, but it’s not structured programming and is a
little
like a goto. Break can improve readability on small loops, but on large
loops
maintained by multiple people it can become a nightmare.

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid


#12

I did, and I was curious about the statement

Because it’s hard for users to tell

begin end while

works differently from

while

in what ways are they different? Any code examples to show the
difference?


#13

The begin end one functions like a do while loop, the body will always
get executed at least once, wherease the while will
only get exectuted if the cond is true.

irb(main):001:0> begin
irb(main):002:1* p “once”
irb(main):003:1> end while nil
“once”
=> nil
irb(main):004:0> p “once” while nil
=> nil

  • Andy D.

#14

On 12/12/05, Steve L. removed_email_address@domain.invalid wrote:

On Monday 12 December 2005 05:42 pm, James Edward G. II wrote:

loop do

… some action …

break unless …
end

I do this quite a bit, but it’s not structured programming and is a little
like a goto.

I see no similarity. ‘goto’ is unstructured because the target point
is completely arbitrary; place a label in your code then jump right to
it. ‘break’ is completely structured; it’s part of the structure of
the enclosing loop and its target is defined by that structure.

Break can improve readability on small loops, but on large loops
maintained by multiple people it can become a nightmare.

I agree with James; if the loop is long enough or complex enough for
these to be a problem, the body of the loop probably needs some
serious refactoring.

Jacob F.


#15

On Tuesday 13 December 2005 11:09 am, Jacob F. wrote:

I see no similarity. ‘goto’ is unstructured because the target point
is completely arbitrary; place a label in your code then jump right to
it. ‘break’ is completely structured; it’s part of the structure of
the enclosing loop and its target is defined by that structure.

Ahh – I found a reference. See
http://en.wikipedia.org/wiki/Structured_programming, and note Dijkstra’s
structured programming definition – every block of code has one entry
point
and one exit point. Break statements clearly violate the “one exit
point”
rule. I was taught the Dijkstra definition at Santa Monica College.

That same page also lists a definition not demanding a single exit
point,
allowing for break. I saw a lot of that when I left Santa Monica College
and
programmed in the real world. I also saw code that was horribly
obfuscated by
break statements. More on that…

Break can improve readability on small loops, but on large loops
maintained by multiple people it can become a nightmare.

I agree with James; if the loop is long enough or complex enough for
these to be a problem, the body of the loop probably needs some
serious refactoring.

It absolutely does. Trouble is, in many shops loops start out 8 lines of
code,
and over many, many years, maintenance programmers, many not
experienced,
most not being privy to original design considerations, add features
demanded
by management on ultra-tight schedules. A few years later it’s 100 lines
of
code and the break statement is in the middle of it.

Under those circumstances, the once understandable break statement
authored by
the original programmer can result in unfathomable code, especially if
others
add more break statements.

What I’m saying isn’t as important today as it was 15 years ago, when
many
programs were not object oriented. Obviously, something like
My_data.to_s can
easily be refactored just from its name. 15 years ago,
process_all_valid_incoming_paid_records() could not be.

By habit, I always think twice before using break or continue (redo in
Ruby).
If I still want to use it, then I go ahead.

SteveT

Steve L.
http://www.troubleshooters.com
removed_email_address@domain.invalid


#16

On Dec 13, 2005, at 7:20 PM, Steve L. wrote:

entry point
and one exit point.

The loop do … end construct is infinite. You must add a break to
end it. With one break, it has exactly one entry and exit point.

experienced,
most not being privy to original design considerations, add
features demanded
by management on ultra-tight schedules. A few years later it’s 100
lines of
code and the break statement is in the middle of it.

You may be describing where you work, but you are certainly not
describing where I do. :wink:

I’ve got two words for you: Unit tests. They were invented to
address every single issue you just listed (plus some!) and I assure
you, they work. You really, really should give them a try. It will
be the best gift you ever give yourself, I promise.

James Edward G. II


#17

Ok, I admit I’m coming onto this thread a bit late in the game, so
someone else might have already suggested this:

i = 0
begin
puts i
i += 1
end until i > 10

  • Jamis

#18

Mark E. wrote:

Because it’s hard for users to tell

begin end while

works differently from

while

in what ways are they different? Any code examples to show the difference?

Andy already answered, but I thought I’d take my shot at it too.

 begin <code> end while <cond>

is guaranteed to execute at least one time; whereas,

 <code> while <cond>

may never execute because it is exactly equivalent to

 while <cond> <code>

in the same way that

 if <cond> <code>

is equivalent to

 <code> if <cond>

The whole begin/end thing is definitely unnecessary, and can (and
frequently does) become a source of confusion; it’s a good thing that
it’s going away. The sooner the better.

–Steve


#19

On Dec 14, 2005, at 2:38 AM, Chad P. wrote:

On the other hand, coding
in a manner that is in any way less easy to maintain because you know
that the way you write code will ensure that the problem is taken care
of doesn’t address the issue of what happens if someone else, with
less
ingrained good habits, comes along and takes over.

At the risk of sounding like a broken record, I think one of the big
advantages of Unit Tests is that they encourage you to code in a
manner that is easier to maintain (because it’s also easier to test).

As for when someone else jumps in, you show them your test suit and
how it works and pray it’s catching. :wink: Seriously, you have to
worry about you first. The rest of the world takes time. (I did ask
in my last job interview if the company covered their software with
Unit Tests though! :smiley: )

James Edward G. II


#20

On 12/13/05, Steve L. removed_email_address@domain.invalid wrote:

I see no similarity. ‘goto’ is unstructured because the target point
is completely arbitrary; place a label in your code then jump right to
it. ‘break’ is completely structured; it’s part of the structure of
the enclosing loop and its target is defined by that structure.

Ahh – I found a reference. See
http://en.wikipedia.org/wiki/Structured_programming, and note Dijkstra’s
structured programming definition – every block of code has one entry point
and one exit point. Break statements clearly violate the “one exit point”
rule. I was taught the Dijkstra definition at Santa Monica College.

I’ll concede that, but refer to James comment (about one break in a
loop do…end being a single exit point). However, I’d lean towards
the looser definition you mention below. Otherwise, having a function
with more than one return in it (e.g. “return false unless
precondition”) would not be structured, and I’d much rather be able to
return early then have to wrap the remainder of the function body in
an if statement.

That same page also lists a definition not demanding a single exit point,
allowing for break. I saw a lot of that when I left Santa Monica College and
programmed in the real world. I also saw code that was horribly obfuscated by
break statements. More on that…

Just because break can be abused doesn’t make it wrong.

by management on ultra-tight schedules. A few years later it’s 100 lines of
code and the break statement is in the middle of it.

Hence the need for continuous refactoring. If that’s not taking place,
it management’s and/or the developers’ fault, not the break
statement’s.

Under those circumstances, the once understandable break statement authored by
the original programmer can result in unfathomable code, especially if others
add more break statements.

Again, abuse doesn’t mean the item being abused is at fault.

What I’m saying isn’t as important today as it was 15 years ago, when many
programs were not object oriented. Obviously, something like My_data.to_s can
easily be refactored just from its name. 15 years ago,
process_all_valid_incoming_paid_records() could not be.

Point conceded.

By habit, I always think twice before using break or continue (redo in Ruby).
If I still want to use it, then I go ahead.

That’s a good principle, one I wish many programmers would follow. I,
too, have been bitten by unclear breaks. But I’ve also been bitten by
unclear conditions in ‘if’ statements, ‘while’ statements when ‘each’
with a block should have been used, etc. That doesn’t mean that ‘if’
statements or ‘while’ statements should be considered harmful. This is
the impression I got about your opinion regarding ‘break’ when you
lumped it with ‘goto’.

Jacob F.