2

Does R allow to define variables within a while-statement? I have a while loop that should continue as long as one of two conditions is true. However, I also need the result of both conditions within the while loop. The functions that compute the conditions are computationally expensive and thus simply re-computing them is not an option.

while (a = conditionA() || b = conditionB())
{
  do_some_work(a)
  some_more_work(a, b)
}

My current work around is the following.

a = conditionA()
b = conditionB()

while (a || b)
{
  do_some_work(a)
  some_more_work(a, b)

  a = conditionA()
  b = conditionB()
}

However, you all understand that this solution just feels wrong. Among others, it pollutes the scope outside the while loop and it is just not preferred to add the unnecessary lines of code.

Alternatively, we can use repeat as explained in the post referred to in the comment. Although this avoids polluting the scope outside the loop, IMO it is less readable than defining variables within the while statement.

repeat
{
  a = conditionA()
  b = conditionB()

  if (!a && !b)
    break

  do_some_work(a)
  some_more_work(a, b)
}
  • Maybe this can help: [do-while loop in R](https://stackoverflow.com/questions/4357827/do-while-loop-in-r) – Lazar Bojanic Oct 19 '20 at 16:00
  • For me, the second block is the idiomatic way to use `while` in `R`. Furthermore, it is also the way I'd do it in `C++` as there is no gain for the compiler and it feels more readable to me. I guess it is a matter of taste. – Jon Nagra Oct 19 '20 at 16:18

1 Answers1

2

You can use <- inside the condition:

conditionA <- function() sample(c(T,F), 1)
conditionB <- function() sample(c(T,F), 1)

do_some_work <- function(a) cat("a", a, fill = TRUE)
do_some_more_work <- function(a, b) cat("a", a, "b", b, fill = TRUE)

set.seed(1)
while((a <- conditionA()) | (b <- conditionB())){
 
 do_some_work(a)
 do_some_more_work(a,b)
 
}
#> a TRUE
#> a TRUE b FALSE
#> a TRUE
#> a TRUE b TRUE
#> a FALSE
#> a FALSE b TRUE
#> a TRUE
#> a TRUE b TRUE

# The loop ends when both a and b are FALSE
a
#> [1] FALSE
b
#> [1] FALSE

Created on 2020-10-19 by the reprex package (v0.3.0)

It doesn't work if you use ||.

If you really want to use ||, you need to write your while statement this way:

while({a <- conditionA(); b <- conditionB(); a || b}){

 # ...

}
Edo
  • 7,567
  • 2
  • 9
  • 19