16
$\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
    Mar 18, 2014 at 10:06
  • 2
    $\begingroup$ Not sure how a compound statement is abuse...first example under scope in the docs does it in compact form. $\endgroup$
    – ciao
    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
    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
    Mar 18, 2014 at 10:29
  • 1
    $\begingroup$ DoWhile exists as a function and as a macro rule in GeneralUtilities` . $\endgroup$
    – Karsten7
    Oct 5, 2016 at 6:41

3 Answers 3

17
$\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
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
    Mar 18, 2014 at 16:24
  • $\begingroup$ @Kuba what do you mean? I'm afraid I don't understand. $\endgroup$
    – Greg Hurst
    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
    Mar 18, 2014 at 18:37
  • $\begingroup$ Oh haha, got it! $\endgroup$
    – Greg Hurst
    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$

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