R / CHAPTER 07

Functions and controlled iteration

Intermediate

Write reusable functions with clear scalar decisions and empty-input behavior.

By the end of this chapter

  • Define and call functions
  • Distinguish scalar and vector conditions
  • Iterate safely over possibly empty input

The idea

An R function receives arguments in its own evaluation environment and returns the last evaluated expression unless return is used earlier. Keep its input assumptions and output shape clear. A function that produces one number should do so on every supported path, including empty input. Local working names help isolate a calculation, while returning the result lets a caller decide how to display or combine it.

An if condition must provide one nonmissing logical value. Use vectorized comparisons to create a selector, or a loop when each step needs a separate decision. seq_along(x) creates valid positions even when x is empty; the expression 1:length(x) does not. Choose && for a short-circuit scalar condition and & when you need an elementwise logical operation.

R example
positive_total <- function(x) {
  total <- 0
  for (i in seq_along(x)) {
    if (!is.na(x[i]) && x[i] > 0) total <- total + x[i]
  }
  total
}
cat(positive_total(c(4, -2, NA, 3)), "
", sep = "")
cat(positive_total(numeric(0)), "
", sep = "")
Result
7
0

The function adds the two positive known entries. For empty input, seq_along produces no positions and the initialized total is returned unchanged.

Try it yourself

Write a function returning the first index of a negative known value, or NA_integer_ when none exists.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

What does this print?
f <- function(x) { x <- x + 2; x * 3 }
cat(f(4))