Chapter 9: Functions
Shih Chien University
2026-08-03
Functions evaluate input arguments and return an output value. The definition syntax is
where arguments is a set of symbol names (optionally with default values) available inside the body, and body is an R expression. Braces are customary but optional for a single expression — these two are equivalent:
Give an argument a default value and callers may omit it; omit a required argument and the error arrives only when the function tries to use it:
[1] 3
[1] 11
[1] 3
Error in `f()`:
! 缺少引數 "y",也沒有預設值
Note
A function that simply never touches an uninitialized argument runs fine. You can even detect missing arguments yourself — e.g., inspecting as.list(match.call()) for a NULL entry — but in practice, put defaults in the signature: it keeps functions clear and readable.
The ellipsis ... means “all the other arguments.” Two main uses. First, passing extras through to another function — here everything after x flows into summary:
[1] "Here is the summary for v."
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.0 5.1 7.1 6.7 8.7 10.0
(Recall from Chapter 7 that ... is a special object type, manipulable only inside a function body.)
Second, you can consume the variable arguments yourself, by converting ... to a list. A function that sums all its arguments:
[1] 2
[1] 15
Individual items are also reachable directly as ..1, ..2, … (any ..n works). And named arguments remain valid symbols inside the body (scoping: Chapter 8).
An explicit return works as in other languages — but R simply returns the last evaluated expression, so return is commonly omitted:
Use the explicit form when it makes the code cleaner — e.g., early exits.
Many R functions accept other functions as arguments (modeling functions, for instance, take a function describing how to treat missing values). The classic example is sapply, which applies a function to every element of a vector:
A toy example — sqrt(1:7) does the same — but many useful functions don’t accept multi-element vectors, and sapply extends them gracefully. (The whole family of summarizing relatives: Chapter 12.)
Functions are objects, so they don’t need names. A function passed without ever being named is anonymous. A minimal demonstration — a function that applies its argument to the number 3:
How the interpreter reads it: f is bound to the anonymous function(x) {x * 7}; evaluating f(3) binds x to 3; the body returns 3 * 7 = 21.
The everyday use: passing one-off functions to apply-style functions:
This family is a real alternative to control structures. Squaring each element with a loop versus an apply:
[1] 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361
[20] 400
[1] 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361
[20] 400
The second version states its intent — apply this function to each element — and is faster, too (Chapter 24).
You can define an anonymous function and call it on the spot — but the function object must be wrapped in parentheses:
Why? Function calls f(arguments) bind very tightly. Without the parentheses, function(x) {x+1}(1) quietly defines a function whose body is {x+1}(1) — no error appears, because the body isn’t evaluated yet. Valid R, almost certainly not what you meant.
To see what arguments a function accepts, args returns a function object with a NULL body:
function (x)
NULL
function (name)
NULL
function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...)
NULL
To manipulate the argument list from code, use formals, which returns a pairlist — one pair per argument, value NULL where no default exists. (formals works only on closures, not built-ins.)
formals also works on the left-hand side of an assignment — change a default in place:
The convenience function alist builds an argument list using definition syntax (note: an argument with no default still needs its equals sign):
The body, too, is readable and writable — it is a language object (typeof(body(f)) is "language"); assign quoted code (the book uses expression(), which also works):
{
x + y + z
}
function (x, y = 100, z = 200)
{
x * y * z
}
Functions are data, all the way down: arguments and body alike can be inspected and rewritten by ordinary R code.
Inside a function, arguments are accessed by the names from the definition:
Callers may specify arguments three ways, matched in priority order:
[1] 5
[1] 5
[1] 5
One caution: with generic functions the name of the dispatching argument varies between methods (x, object, …), so passing the dispatching object positionally is the most portable habit.
Exact names cost keystrokes but buy readability and remove ambiguity. Partial matching is discouraged for good reason (R can warn about it via options(warnPartialMatchArgs=TRUE)):
Error in `f()`:
! 引數 1 有多個與之相對應的形式引數
[1] "arg1: 1"
[1] "arg2: 2"
[1] "arg1: 2"
[1] "arg2: 1"
The same prefix lands on different arguments depending on what else is supplied — a recipe for silent bugs.
Every function returns a value; some also change variables in other environments, draw graphics, read or write files, or talk to the network. These extra actions are side effects.
The key side-effecting operator is <<-. The statement var <<- value skips the current environment and searches the enclosing environments upward for an existing var; if the global environment is reached without a match, the assignment happens there:
Two more families of side effects round out the picture:
Tip
Design habit: keep most functions pure (no side effects) and concentrate the side effects in a few clearly named places. Pure functions are easier to test, reuse, and parallelize.
Copyright. These slides are adapted from R in a Nutshell: A Desktop Quick Reference (2nd ed.) by Joseph Adler, O’Reilly Media. All rights reserved by the original author and publisher.
Non-commercial use only. These materials are strictly for educational purposes and may not be used for commercial gain.
Attribution. Any reproduction, distribution, or use of these materials must properly credit the original source.
R in a Nutshell: A Desktop Quick Reference