Lesson 8 / 25
Functions, Defaults, Dots and Pipes
Write functions with defaults and ..., and chain operations with the pipe.
Reusable building blocks
Define functions with function(args) { body }; the last evaluated expression is returned automatically (use return() for early exits). Arguments can have defaults and can be matched by name, so calls such as round(x, digits = 1) are clear. The special argument ... (dots) passes extra arguments through to other functions, as in wrappers around mean() or ggplot(). R uses lazy evaluation: arguments are evaluated only when used. Since R 4.1, anonymous functions have a short form, \(x) x * 2, and the native pipe |> passes the left-hand value as the first argument of the next call, turning nested calls into readable steps (data |> filter(...) |> summarise(...)). The magrittr pipe %>% from the tidyverse predates it and works similarly, with a few extra features. Functions are objects: you can store them in lists and pass them to other functions. Validate inputs early with stopifnot() or stop("message"), and signal problems with warning() and message().
A validated function and a pipeline
Defaults, dots, input checks and the native pipe.
gst_total <- function(amount, rate = 0.18, digits = 2) {
stopifnot(is.numeric(amount), all(amount >= 0, na.rm = TRUE))
round(amount * (1 + rate), digits)
}
gst_total(c(100, 250)) # 118.0 295.0
gst_total(100, rate = 0.05) # named argument
safe_mean <- function(x, ...) {
if (length(x) == 0) return(NA_real_) # early return
mean(x, ...) # pass extra arguments such as na.rm
}
safe_mean(c(1, NA, 3), na.rm = TRUE) # 2
square <- \(x) x^2 # short anonymous function (R 4.1+)
c(4, 9, 16) |>
sqrt() |>
sum() |>
square() # (2 + 3 + 4)^2 = 81An assembly line
Nested calls like square(sum(sqrt(x))) must be read inside out. A pipe is an assembly line: the data moves left to right through each station in the order the work happens.
Quick check: What does the native pipe `x |> f(y)` mean?
- f(y, x)
- x(f, y)
- It assigns f to x
- f(x, y)
Answer
f(x, y) — The pipe inserts the left-hand value as the first argument of the right-hand call.