Could we have a do while loop in Julia?

Hi all,

I am having a GREAT time writing Julia code! I write a lot of machine learning code that requires some kind of optimisation/decent and so on and I am missing the do-while construct. Most code I write requires the calculation to be done once before it hits a condition, so I end up kind of executing the code once outside a while loop before entering the loop or doing some other kind of kludge, which is unfortunate given how lovely and clean everything else is :slightly_smiling_face:

I think the language would really benefit from adding a do-while loop given that its main focus is writing numerical algorithms.

Thank you kindly. :wink:

1 Like

I’m not familiar with do-while loops, but are they significantly different from a pattern like this:

condition = true
while condition
    result = process()
    condition = foo(result)
end

?

Can you give an example (preferably simple) that illustrates a usecase?

2 Likes

or

while true
    stop_condition() && break
end

etc.

8 Likes

@DNF Good point!

I usually just write something like

#... do calc ...
while calcError(...) > epsilon
  # ... do calc ...
end

You still have to create the condition variable and make sure that it is correctly updated inside the body of your calculation. I guess the do-while isn’t so essential, and I got a little “code blind”, but still a nice to have I think.

I avoid using while true, seems like a bug waiting to happen.

3 Likes

I don’t quite see why.

In any case, what you are asking for is possible with existing control flow constructs, so there is no need for a new one.

1 Like

You’re separating the condition you care about from where it’s actually supposed to be set. It means if anyone messes with that condition or you forget what it’s for, you break your code. It’s different from the conditional break which is clear and obvious, it’s the main loop which I don’t like to mess with.

To me while true is a bug, I don’t like to write them.

3 Likes

I for one am massively in favour of extending the set of control flow constructs.

The thing with replies like “but you can already do it, here’s how” is that no-one is actually doubting that julia is turing-complete – it’s just that sometimes a certain control construct describes your intention better than another. After all, we do have for even though it can be expressed as while, and we have while even though it can be expressed as @goto. (In fact, by the time you get to while true, you are at @goto levels of expressiveness in my opinion.)

The better you can communicate your intention to whoever reads your code (a reviewer, a contributor, or yourself by the time you forgot what you were thinking when you wrote this), the smoother the development process.

Having said that, unfortunately, I don’t think we can easily create a do/while construct for parsing reasons (while doesn’t close a block; in fact, we want to allow nesting it). And introducing a new keyword (e.g. do/until) can’t happen until julia 2.0. So I don’t see a particular implementation of this happening any time soon, if at all.

18 Likes

It’s pretty easy to create a macro to give you almost exactly the syntax you’re looking for. For example: https://gist.github.com/MikeInnes/8299575 (see @once_then) or: https://en.m.wikibooks.org/wiki/Introducing_Julia/Metaprogramming (see @until, which is a different structure but illustrates the basic idea).

5 Likes

Yeah, but that’s a dependency I have to keep track of. It’s a fairly basic thing that doesn’t ship with Julia. I’d rather live with the current situation and hope that it changes than load a “juliakludge” library every time I write code.

In general I agree with this, but

while true
   ...
end

is so common that it can be considered a standard idiom, where the reader expects to look for a breaking condition, assuming that implementing an infinite loop was not the intention.

Simple grepping in Julia sources shows 250+ instances of while true.

11 Likes

Since using a package has such a low cost, IMO the willingness to consider a package for something is a good test of whether you seriously need it.

1 Like

A package is an operational need - I generally try to use as few as possible. Syntax is quality of life, nicer code to write/read and so on … I think I made it clear at the start.

I would suggest embracing while true. Almost every while loop I write starts out as a while true loop. Why? Because I generally don’t know what the exit condition is or where I’m going to exit from when I start writing a loop. I can write any loop as a while true with break calls to exit. Then if I notice that one of the exits ends up as the very first thing in the loop—or maybe the very last with the ability to move to the beginning without loss of generality—I’ll turn it into a while cond loop.

17 Likes

Okay, since it’s you I’ll definitely give it a try.

3 Likes

Give it a try! Once I started doing this I found it very liberating. Otherwise I would get stuck in “while condition paralysis”—trying to figure out what the condition needs to be before I really had enough information to do so. Instead, now I just write while true and get into the meat of the loop and figure out the exit points when I get to them.

16 Likes

While I don’t think it’s such a bad thing and I wouldn’t be afraid to use it if I really thought it was appropriate, I will admit that while true makes me just a little nervous. That said, I so rarely find myself unable to write a for loop, even if those for loops have break statements in them.

6 Likes

First, I think this is a good suggestion. I totally understand your feeling, since you are writing something like

#... do calc ...
while condition
  # ... do calc ...
end

do while is really a grammar sugar or syntactic sugar when

#... do calc ...

has many lines. Definitely you do not want to duplicate them.

However, since there is no do while in Julia so far, I think

while true
  # ... do calc ...
  if condition
    break
end

is one of the best choices… It is not a bug, as it is actually kind of standard for professional programmers…, for example, the “listening” mechanism…

The key point is that the loop should break when the condition is met.

But I support your suggestion. Personally I like the grammar sugar “do while”.

2 Likes

FYI I usually end up functionalizing #... do calc ... for example doCalc(MyObject, ...) so before the while loop it’s really just one line; inside the while loop I use the function but other adjustments are made and other things can happen depending on the state of MyObject. I end up with something like:

doCalc(MyObject, ...)
while calcError(MyObject, ...) > epsilon
  doCalc(MyObject, ...)
  # ... maybe do other stuff ...
end

I looked at that and thought, it would be nice to do:

do
  doCalc(MyObject, ...)
  #... maybe do other stuff ...
  until calcError(MyObject, ...) <= epsilon
end 
1 Like

that’s absolutely the point and why we prefer the grammar sugar do while.