Flow of code execution

R language constructs for flow control

Author

Pedro J. Aphalo

Published

2023-11-18

Modified

2023-11-18

Abstract

Interactive examples and flow chart diagrams for R language constructs for conditional evaluation and for repeated evaluation of code statements.

Keywords

programming, webr-based

1 Introduction

In a simple script the code statements are run (= executed, = evaluated) one after another as they appear in the file, from top to bottom. A simple script then always runs the same statements carrying out each time the script is run the same computations.

This restriction is removed by including control constructs that based on a test condition decide which code statement to run next. Using this constructs we can make the computations done depend on data and their properties. This is when programming starts being most useful or “powerful”, because the same code in scripts (or packages) becomes useful with many different datasets.

We can group these constructs used to control the flow of code execution from statement to statement in two groups: those that work as ON/OFF switches and those that implement the repeated execution of a statement, or iteration.

To make this work usefully, we need one more construct: a construct to assemble a compound code statement from multiple simple code statements. This makes it possible for the control constructs mentioned above to control groups of statements or “chunks” of code in addition to simple statements.

Below, we start with the sequential execution of statements in their “natural” ordering and grouping into compound statements. Next, we look and the ON/OFF or YES/NO constrtucts (if, if ... else and ifelse). Last we look at the iteration or “repeated execution” control constructs (for (), while() and repeat).

Playgrounds or interactive R examples

Within this page you will run R examples in the web browser. You can edit these code examples and run them again as many times as you like, by clicking on the Run Code button above the ‘WebR’ text panels.

2 Unconditional execution

2.1 Sequence

A flow chart

Flow diagram of sequential evaluation of code statements
Code
a <- 123
b <- a * 2
print(b)
[1] 246
Playground

2.2 Compound statement

Flow chart showing two code statements enclosed within a box.

A compound statement containing two statements and their sequence of evaluation..

A group code statements enclosed in { } conform a compoud statement. By itself this construct does not modify the sequence in which statements are executed or evaluated.

Code
a <- 123
{
  b <- a * 2
  print(b)
}
[1] 246
Playground

3 Conditional execution

Decisions about which statement to run next are based on the result of a test returning a logical value, TRUEorFALSE`.

3.1 if () statement

A flow chart showing two alternative paths downstream of a decision.

Flow diagram of an `if ()` control construct showing the alternative paths of evalaution.

In an if statement, the decision is based on the value of a logical vector of length one.

Code
a <- 123
if (a > 0) {
  print("'a' is positive")
}
[1] "'a' is positive"
Code
print(a)
[1] 123
Playground

3.2 if ()... else statement

Flow chart with two paths downstream of the decision.

Flow diagram of an `if ()` control construct showing the alternative paths of evaluation.
Code
a <- 123
if (a >= 0) {
  print("'a' is positive")
} else {
  print("'a' is negative")
}
[1] "'a' is positive"
Code
print(a)
[1] 123
Playground

For dealing with vectors longer that one we can use all() and any(). Of course, if they describe the decision we need to process our data.

An advanced/more sophisticated alternative is to count the number of members in the vector that are positive and negative.

3.3 switch statement

In a switch statement the decision selects the evaluation of one among multiple alternative staements. The “selector” can be an integer or a character vector of length equal to one.

Flow chart with multiple parallel paths for evaluation.

Flow diagram showing multiple alternative code statements with evaluation controlled by a `switch()` statement.

Using names for the cases in the switch.

Code
my.char <- "two"
my.fraction <- switch(my.char,
                      one = 1,
                      two = 1 / 2,
                      four = 1 / 4,
                      0
)
print(my.fraction)
[1] 0.5
Playground

Using numbers to select cases by position.

Playground

3.4 ifelse(...) vectorised statement

Function ifelse() works very differently than if () ... else. The decision can, and in most cases, it is based on a long logical vector. The returned value has the same length as the logical vector.

Code
a <- c(1, 2, -1, 3) # a vector of length 3
ifelse(a >= 0, "positive", "negative")
[1] "positive" "positive" "negative" "positive"
Code
print(a)
[1]  1  2 -1  3
Playground

4 Iteration or repeated execution

4.1 for () statement

Flow chart showing a closed execution path with an entry and an exit.

Flow diagram of a `for ()` loop, showing the compound statement that is evaluated repeatedly.

In a for statement, the controlled statement is run with one member of a list or vector at a time, normally walking from “head” to “tail” of the list or vector. The value of each member is accessed through a “place holder” variable. The name of the arbitrary variable can be any valid R name.

Code
a <- c(1, 2, -1, 3)
for (a_member in a) {
  print(a_member)
}
[1] 1
[1] 2
[1] -1
[1] 3
Code
print(a)
[1]  1  2 -1  3
Playground

Using extraction operator [ ] and indexing.

We can end early.

We can jump to the next.

4.2 while() statement

Flow chart with a closed loop with an entry and an exit point.

Flow diagram of an `while()` control construct showing the closed loop containing a statement repeatedly evaluated.
Code
a <- c(1, 2, -1, 3)
i <- 0
sum_of_a <- 0
while(i < length(a)) {
  i <- i + 1
  sum_of_a <- sum_of_a + a[i]
  print(sum_of_a)
}
[1] 1
[1] 3
[1] 2
[1] 5
Code
print(i)
[1] 4
Playground

4.3 repeat statement

Flow chart with a loop with an exit point at an arbitrary point within the loop.

Flow diagram of an `repeat` control construct showing one statement repeatedly evaluated in a loop-shaped path
Code
a <- c(1, 2, -1, 3)
i <- 0
sum_of_a <- 0
while(i < length(a)) {
  i <- i + 1
  sum_of_a <- sum_of_a + a[i]
  print(sum_of_a)
}
[1] 1
[1] 3
[1] 2
[1] 5
Code
print(i)
[1] 4
Playground

5 Take home message

Now you know all the important constructs that make it possible to control the flow of evaluation of statements in a script or program. With small variations in their syntax, these same constructs are available in many different computer programming languages.

That all these constructs are available in R, makes of R a proper programming language. It also means that learning to program in additional computer languages is much easier than learning the first one.