Control
Control Flow
These are the basic control-flow constructs of the R language. They function in much the same way as control statements in any Algol-like language. They are all reserved words.
- Keywords
- programming, logic, iteration
Usage
if(cond) expr
if(cond) cons.expr else alt.exprfor(var in seq) expr
while(cond) expr
repeat expr
break
next
Arguments
- cond
A length-one logical vector that is not
NA
. Conditions of length greater than one are currently accepted with a warning, but only the first element is used. An error is signalled instead when the environment variable_R_CHECK_LENGTH_1_CONDITION_
is set to true. Other types are coerced to logical if possible, ignoring any class.- var
A syntactical name for a variable.
- seq
An expression evaluating to a vector (including a list and an expression) or to a pairlist or
NULL
. A factor value will be coerced to a character vector.- expr, cons.expr, alt.expr
An expression in a formal sense. This is either a simple expression or a so called compound expression, usually of the form
{ expr1 ; expr2 }
.
Details
break
breaks out of a for
, while
or repeat
loop; control is transferred to the first statement outside the
inner-most loop. next
halts the processing of the current
iteration and advances the looping index. Both break
and
next
apply only to the innermost of nested loops.
Note that it is a common mistake to forget to put braces ({ .. }
)
around your statements, e.g., after if(..)
or for(....)
.
In particular, you should not have a newline between }
and
else
to avoid a syntax error in entering a if ... else
construct at the keyboard or via source
.
For that reason, one (somewhat extreme) attitude of defensive programming
is to always use braces, e.g., for if
clauses.
The seq
in a for
loop is evaluated at the start of
the loop; changing it subsequently does not affect the loop. If
seq
has length zero the body of the loop is skipped. Otherwise the
variable var
is assigned in turn the value of each element of
seq
. You can assign to var
within the body of the loop,
but this will not affect the next iteration. When the loop terminates,
var
remains as a variable containing its latest value.
Value
if
returns the value of the expression evaluated, or
NULL
invisibly if none was (which may happen if there is no
else
).
for
, while
and repeat
return NULL
invisibly.
for
sets var
to the last used element of seq
,
or to NULL
if it was of length zero.
break
and next
do not return a value as they transfer
control within the loop.
References
Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New S Language. Wadsworth & Brooks/Cole.
See Also
Syntax
for the basic R syntax and operators,
Paren
for parentheses and braces.
Examples
library(base)
# NOT RUN {
for(i in 1:5) print(1:i)
for(n in c(2,5,10,20,50)) {
x <- stats::rnorm(n)
cat(n, ": ", sum(x^2), "\n", sep = "")
}
f <- factor(sample(letters[1:5], 10, replace = TRUE))
for(i in unique(f)) print(i)
# }
Community examples
Use if to only run code that satisfies a condition. ```{r} x <- 1 if(x > 0) { message("x is positive") } ``` Use an else clause to run code when the condition isn't satisfied. ```{r} x <- -1 if(x > 0) { message("x is positive") } else { message("x is negative") } ``` You can chain together as many if blocks as you like (but see the [`switch()`](https://www.rdocumentation.org/packages/base/topics/switch) function for a better way to deal with this.) ```{r} x <- 0 if(x > 0) { message("x is positive") } else if(x < 0) { message("x is negative") } else { message("x is zero") } ``` Use `repeat()` to repeat code. You need to include a `break` statement, or it will repeat forever. (This is type of loop is often called "do-while" in other languages.) ```{r} i <- 1 repeat{ message("Inside the ", i, "th iteration of a repeat loop.") flush.console() if(runif(1) > 0.95) { break } i <- i + 1 } ``` `while` loops work the same, but have the exit condition at the start. (This means that they may never enter the loop body, whereas `repeat` loops always run at least once.) ```{r} i <- 1 while(runif(1) < 0.95) { message("Inside the ", i, "th iteration of a while loop.") flush.console() i <- i + 1 } ``` `for` loops repeat the same action a specified number of times. Look closely: `in` is not the same as `%in%`! ```{r} for(i in seq_len(5)) { message("Inside the ", i, "th iteration of a for loop.") } ``` You don't have to loop over numbers, you can loop over any vector. ```{r} (f <- factor(sample(letters[1:5], 10, replace = TRUE))) for(level in levels(f)) { n <- sum(f == level) message( "There ", ngettext(n, "is ", "are "), n, ngettext(n, " instance", " instances"), " of ", level, " in f." ) } ``` Under most circumstances, using [`lapply()`](https://www.rdocumentation.org/packages/base/topics/lapply) (or a variant like `sapply()`) will result in cleaner code than a for loop. This is full of boilerplate code and fairly awful: ```{r} n <- c(2, 5, 10, 20, 50) sum_of_squares <- numeric(length(n)) for(i in seq_along(n)) { x <- stats::rnorm(n[i]) sum_of_squares[i] <- sum(x ^ 2) } sum_of_squares ``` This is cleaner. ```{r} n <- c(2, 5, 10, 20, 50) sapply( n, function(ni) { x <- stats::rnorm(ni) sum(x ^ 2) } ) ``` Sometimes you want to discontinue the current iteration of a loop and move to the next one. ```{r} loaded_die <- function() { repeat{ y <- sample(1:6, 1) if(y < 6) { message("Let me try again.") next } message("I'm feeling lucky tonight!") break } y } loaded_die() ```