Control Flow

if needs a single TRUE/FALSE; use ifelse() / dplyr::if_else() / dplyr::case_when() for vectors.

8.1 if / else

if needs a single TRUE/FALSE; use ifelse() / dplyr::if_else() / dplyr::case_when() for vectors.

x <- 7
if (x > 5) {
  print("big")
} else if (x > 2) {
  print("medium")
} else {
  print("small")
}

label <- if (x %% 2 == 0) "even" else "odd"   # if is an expression

8.2 Vectorized conditionals

ifelse(c(1, 6, 3) > 4, "high", "low")
dplyr::case_when(
  x < 3 ~ "low",
  x < 7 ~ "medium",
  .default = "high"
)

8.3 switch

f <- function(type) {
  switch(type,
    mean = "Average",
    median = ,                 # fall-through to the next value
    middle = "Middle value",
    stop("Unknown type: ", type))
}
f("median")   # "Middle value"
switch(2, "a", "b", "c")   # "b" (numeric index)

8.4 for loops

for (i in 1:5) print(i^2)

fruits <- c("apple", "banana")
for (f in fruits) cat("I like", f, "\n")

for (i in seq_along(fruits)) cat(i, fruits[i], "\n")   # safe even when empty

# Pre-allocate output for speed
out <- numeric(10)
for (i in seq_len(10)) out[i] <- i^2

8.5 while, repeat, break, next

i <- 1
while (i <= 3) { print(i); i <- i + 1 }

repeat {
  n <- sample(1:10, 1)
  if (n == 7) break
}

for (i in 1:10) {
  if (i %% 2 == 0) next     # skip even numbers
  print(i)
}