20
$\begingroup$

Have I missed something or is there no built-in which mimics the behaviour of do ... while loop?

I am looking for a construct that evaluates procedure once and then repeatedly evaluates it while test is not fulfilled.

I'm ended up using:

While[procedure; test, {}]

But clearly the second argument is redundant, so I have a feeling that I'm missing something. Maybe not, but I just want to be sure :)

$\endgroup$
11
  • 2
    $\begingroup$ While[(procedure;test)] - parens. optional, makes it clear I think... $\endgroup$
    – ciao
    Commented Mar 18, 2014 at 10:06
  • 3
    $\begingroup$ Not sure how a compound statement is abuse...first example under scope in the docs does it in compact form. $\endgroup$
    – ciao
    Commented Mar 18, 2014 at 10:12
  • $\begingroup$ @rasher Agree, abuse is not a good word. I mean, docs say first arg is a test which may be missleading and the example you are referring to is ok but formed in easy-to-overlook way. Especially for new users. I think it could be an useful topic for future visitors. $\endgroup$
    – Kuba
    Commented Mar 18, 2014 at 10:17
  • 1
    $\begingroup$ @rasher To the conclusion: I don't think there should be a separate function. My goal is to show to future beginners :), who may have doubts similar to mine in the past, that this is the way. $\endgroup$
    – Kuba
    Commented Mar 18, 2014 at 10:29
  • 1
    $\begingroup$ DoWhile exists as a function and as a macro rule in GeneralUtilities` . $\endgroup$
    – Karsten7
    Commented Oct 5, 2016 at 6:41

4 Answers 4

18
$\begingroup$

While While[procedure; test] works, it looks very similar to While[test, procedure]. The only difference is ; vs ,. While is not the most commonly used construct, so when used like this there's a high chance of misunderstanding/misreading.

If readability/reliability is a concern (for example a collaboratively developed published package), I'd use the longer but clearer

While[True,
  procedure;
  If[Not[test], Break[]]
]

The only argument here is readability and "defensive programming" (extra effort to avoid accidental problems). Readability is subjective. If you are the only person who writes/reads the code and you get used to this use of While (and thus always pay special attention to the , vs ;) then this argument doesn't apply.

$\endgroup$
0
15
$\begingroup$

Version 13.1 introduced the function Until

Until[test,body] evaluates body and then test, repetitively, until test first gives True.

$\endgroup$
7
$\begingroup$

Why not write your own and place it in your init.m file?

SetAttributes[DoWhile, HoldAll];

DoWhile[procedure_, test_] := While[procedure; test]
$\endgroup$
4
  • $\begingroup$ One point against is that the code with it posted on SE requires explanation :) $\endgroup$
    – Kuba
    Commented Mar 18, 2014 at 16:24
  • 1
    $\begingroup$ @Kuba what do you mean? I'm afraid I don't understand. $\endgroup$
    – Greg Hurst
    Commented Mar 18, 2014 at 18:36
  • $\begingroup$ If I put that in my init file and then post the answer here, using this function, I will have to add definition :) $\endgroup$
    – Kuba
    Commented Mar 18, 2014 at 18:37
  • $\begingroup$ Oh haha, got it! $\endgroup$
    – Greg Hurst
    Commented Mar 18, 2014 at 18:37
4
$\begingroup$

Here's another way to write your own:

SetAttributes[doWhile, HoldAll];    
doWhile[expr_, test_] := CompoundExpression[expr, While[test, expr]]

Or just:

doWhile[expr_, test_] := (expr; While[test, expr])
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.