75

I was wondering about how to write do-while-style loop?

I found this post:

you can use repeat{} and check conditions whereever using if() and exit the loop with the "break" control word.

I am not sure what it exactly means. Can someone please elaborate if you understand it and/or if you have a different solution?

zx8754
  • 52,746
  • 12
  • 114
  • 209
Tim
  • 1
  • 141
  • 372
  • 590
  • 2
    The difference between the answers of @Jericho and @DWin is in wether the "statements" get evaluated. In @Jericho's answer, the loop is run at least once as the break condition comes after the "statements". In @DWin's answer, if `y` started out greater than or equal to 5, the loop would not run at all. Which you prefer will depend upon whether you want the "statements" to run at all or not. – Gavin Simpson Dec 05 '10 at 13:28
  • In conclusion a do while statement does run at least once then checks the condition before looping back to the statements. – A Salcedo Dec 05 '10 at 20:11
  • Therefore, you can use a while loop instead of a do-while loop, if you ensure that the loop (statement) is run at least once by setting the condition to be true before the loop (e.g., with a temporaray variable and an or-connective or) as in Dwin's answer). – Henrik Dec 06 '10 at 11:53

4 Answers4

143

Pretty self explanatory.

repeat{
  statements...
  if(condition){
    break
  }
}

Or something like that I would think. To get the effect of the do while loop, simply check for your condition at the end of the group of statements.

A Salcedo
  • 6,378
  • 8
  • 31
  • 42
  • Is this faster than using while? – Emer Apr 30 '14 at 09:40
  • 4
    A while and a do while are used for different cases. Just consider it this way, while -> 0 to many times execution, do-while 1 to many times execution. I wouldn't see it as faster or slower, there are just sometimes when you want to have execution at least one time and some that you don't. It is nothing more than the placement of the condition. – A Salcedo May 21 '14 at 14:06
  • 2
    To me, 42's answer is true whereas Salcedo's answer is false. In 42's answer, there is a NEGATION in the condition (`repeat( { expressions}; if (! end_cond_expr ) {break} )`). So, do-while EndCondition is simulated by repeat !EndCondition. I checked this fact via a code snippet. – Erdogan CEVHER Jun 13 '17 at 20:07
  • 1
    @ErdoganCEVHER The OP did not define what `condition` means, so I wouldn't call Salcedo's answer false. But you have a good point `if(!condition){break}` aligns better with C's `do{} while(condition)`. – Josiah Yoder Jul 24 '20 at 14:34
33

See ?Control or the R Language Definition:

> y=0
> while(y <5){ print( y<-y+1) }
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

So do_while does not exist as a separate construct in R, but you can fake it with:

repeat( { expressions}; if (! end_cond_expr ) {break} )

If you want to see the help page you cannot type ?while or ?repeat at the console but rather need to use ?'repeat' or ?'while'. All the "control-constructs" including if are on the same page and all need character quoting after the "?" so the interpreter doesn't see them as incomplete code and give you a continuation "+".

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • 3
    This is "while-do", not the requested "do-while". The point is that do-while setup will let you write some commands in one place (not repeated outside and inside the loop block) and guarantee that the intended function is called once. As in this answer here, you see that there are two lines that assign a value to `y` (in the first line and also within the `print` call. To reduce redundancy and reduce bugs in certain situations, it's nice to have do-while so you only assign some variable (e.g. `y`) once. – Kalin Jun 06 '14 at 04:47
  • Forgive me for being obtuse, but what you write is opaque without code example to illuminate. – IRTFM Jun 06 '14 at 05:12
  • 1
    The key is when (and how) the termination condition gets executed. In do-while-loops the condition is tested for truth prior to proceeding with each iteration, whereas in repeat-until-loops the test is conducted at the end of iterations and exited when a TRUE value is seen. – IRTFM Jun 06 '14 at 19:17
  • I just noticed a second downvote for this answer. I'm guessing (which is all I can do since the one demurral so far made no sense to me) that there is some other language (other than R and Pascal) for which this distinction is more important (and different than R). The repeat-until and do-while constructs are somewhat unusual in R programming, so the fine points in some other language might not be obvious to us useRs. – IRTFM Nov 29 '14 at 05:46
  • 1
    Nothing to do with differences in language, it's differences in control flow. `do-while` means: run this block of code once. Check condition. If condition false, run this block of code again. Repeat check condition. `while` means: Check condition. Run this block of code. If condition false, run this block of code again. Repeat check condition. In a `do-while` loop, the condition is checked *after* the code has been executed. In a `while` loop, it's checked *before*. In a `do-while` loop, the code is guaranteed to be executed at least once. In a `while` loop, the code may never be executed. – cazgp Dec 18 '14 at 11:20
  • So you are saying that `do-while` is the same as `repeat-until-not`. – IRTFM Dec 18 '14 at 16:31
  • Do-while first does something then performs a check. While-do will only do something after checking condition. – W7GVR May 14 '15 at 19:46
  • Right. I got the intended distinction. In R there is no `do_while` so to get that behavior one needs to use `repeat {expr}` where `expr` has the test at the end with a test and a `break`, or use the strategy Henrik suggested in his comment. – IRTFM May 14 '15 at 20:38
  • To me, 42's answer is true whereas Salcedo's answer is false. In 42's answer, there is a NEGATION in the condition (`repeat( { expressions}; if (! end_cond_expr ) {break} )`). So, do-while EndCondition is simulated by repeat !EndCondition. I applied 42's logic when converting a Gauss code to R, and putting that negation symbol saved my life. Thx a lot 42 really. – Erdogan CEVHER Jun 13 '17 at 20:06
7

Building on the other answers, I wanted to share an example of using the while loop construct to achieve a do-while behaviour. By using a simple boolean variable in the while condition (initialized to TRUE), and then checking our actual condition later in the if statement. One could also use a break keyword instead of the continue <- FALSE inside the if statement (probably more efficient).

  df <- data.frame(X=c(), R=c())  
  x <- x0
  continue <- TRUE

  while(continue)
  {
    xi <- (11 * x) %% 16
    df <- rbind(df, data.frame(X=x, R=xi))
    x <- xi

    if(xi == x0)
    {
      continue <- FALSE
    }
  }
Daniel D.
  • 134
  • 1
  • 4
  • 7
2

Noticing that user 42-'s perfect approach {
* "do while" = "repeat until not"
* The code equivalence:

do while (condition) # in other language
..statements..
endo

repeat{ # in R
  ..statements..
  if(! condition){ break } # Negation is crucial here!
}

} did not receive enough attention from the others, I'll emphasize and bring forward his approach via a concrete example. If one does not negate the condition in do-while (via ! or by taking negation), then distorted situations (1. value persistence 2. infinite loop) exist depending on the course of the code.

In Gauss:

proc(0)=printvalues(y);
DO WHILE y < 5;    
y+1;
 y=y+1;
ENDO;
ENDP;
printvalues(0); @ run selected code via F4 to get the following @
       1.0000000 
       2.0000000 
       3.0000000 
       4.0000000 
       5.0000000 

In R:

printvalues <- function(y) {
repeat {
 y=y+1;
print(y)
if (! (y < 5) ) {break}   # Negation is crucial here!
}
}
printvalues(0)
# [1] 1
# [1] 2
# [1] 3
# [1] 4
# [1] 5

I still insist that without the negation of the condition in do-while, Salcedo's answer is wrong. One can check this via removing negation symbol in the above code.

Erdogan CEVHER
  • 1,788
  • 1
  • 21
  • 40
  • 2
    I think you are misunderstanding Salcedo's answer. It doesn't have an explicit condition in the pseudocode. You could replace his `(condition)` with `!(y<5)` or you could replace it with `(y>=5)` or whatever you need for the use case. It doesn't have to have a negation symbol, it's just whatever you need the logical condition to be to stop the loop. – matt Dec 05 '17 at 22:58
  • No, I don't misunderstand. What I emphasize is that the "negation" of the specified condition in do-while MUST be used. Math'ly, `!(y<5)` and `(y>=5)` are equivalent. Both are the negation of `(y<5)`. I do NOT insist the usage of "!" negation symbol. One can distribute the negation symbol to the phrase in hand just as `!(y<5)` = `(y>=5)`. – Erdogan CEVHER Dec 06 '17 at 21:32