Chapter 1: R Internal Structures 10
arguments of function calls are evaluated. The rules are different for the internal (special/builtin)
and R-level functions (closures).
For a call to a closure, the actual and formal arguments are matched and a matched call
(another LANGSXP) is constructed. This process first replaces the actual argument list by a list
of promises to the values supplied. It then constructs a new environment which contains the
names of the formal parameters matched to actual or default values: all the matched values
are promises, the defaults as promises to be evaluated in the environment just created. That
environment is then used for the evaluation of the body of the function, and promises will be
forced (and hence actual or default arguments evaluated) when they are encountered. (Evaluat-
ing a promise sets NAMED = NAMEDMAX on its value, so if the argument was a symbol its binding
is regarded as having multiple references during the evaluation of the closure call.)
If the closure is an S3 generic (that is, contains a call to UseMethod) the evaluation process
is the same until the UseMethod call is encountered. At that point the argument on which to do
dispatch (normally the first) will be evaluated if it has not been already. If a method has been
found which is a closure, a new evaluation environment is created for it containing the matched
arguments of the method plus any new variables defined so far during the evaluation of the
body of the generic. (Note that this means changes to the values of the formal arguments in the
body of the generic are discarded when calling the method, but actual argument promises which
have been forced retain the values found when they were forced. On the other hand, missing
arguments have values which are promises to use the default supplied by the method and not
by the generic.) If the method found is a primitive it is called with the matched argument list
of promises (possibly already forced) used for the generic.
The essential difference
5
between special and builtin functions is that the arguments of spe-
cials are not evaluated before the C code is called, and those of builtins are. Note that being a
special/builtin is separate from being primitive or .Internal: quote is a special primitive, + is
a builtin primitive, cbind is a special .Internal and grep is a builtin .Internal.
Many of the internal functions are internal generics, which for specials means that they do
not evaluate their arguments on call, but the C code starts with a call to DispatchOrEval. The
latter evaluates the first argument, and looks for a method based on its class. (If S4 dispatch is
on, S4 methods are looked for first, even for S3 classes.) If it finds a method, it dispatches to
that method with a call based on promises to evaluate the remaining arguments. If no method
is found, the remaining arguments are evaluated before return to the internal generic.
The other way that internal functions can be generic is to be group generic. Most such
functions are builtins (so immediately evaluate all their arguments), and all contain a call to
the C function DispatchGeneric. There are some peculiarities over the number of arguments
for the "Math" group generic, with some members allowing only one argument, some having
two (with a default for the second) and trunc allows one or more but the default method only
accepts one.
1.5.1 Missingness
Actual arguments to (non-internal) R functions can be fewer than are required to match the
formal arguments of the function. Having unmatched formal arguments will not matter if the
argument is never used (by lazy evaluation), but when the argument is evaluated, either its
default value is evaluated (within the evaluation environment of the function) or an error is
thrown with a message along the lines of
argument "foobar" is missing, with no default
Internally missingness is handled by two mechanisms. The object R_MissingArg is used to
indicate that a formal argument has no (default) value. When matching the actual arguments
5
There is currently one other difference: when profiling builtin functions are counted as function calls but
specials are not.