(R-ints.info).Internal vs .Primitive
2 '.Internal' vs '.Primitive'
*****************************
C code compiled into R at build time can be called directly in what are
termed _primitives_ or via the '.Internal' interface, which is very
similar to the '.External' interface except in syntax. More precisely,
R maintains a table of R function names and corresponding C functions to
call, which by convention all start with 'do_' and return a 'SEXP'.
This table ('R_FunTab' in file 'src/main/names.c') also specifies how
many arguments to a function are required or allowed, whether or not the
arguments are to be evaluated before calling, and whether the function
is 'internal' in the sense that it must be accessed via the '.Internal'
interface, or directly accessible in which case it is printed in R as
'.Primitive'.
Functions using '.Internal()' wrapped in a closure are in general
preferred as this ensures standard handling of named and default
arguments. For example, 'grep' is defined as
grep <-
function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,
fixed = FALSE, useBytes = FALSE, invert = FALSE)
{
if (!is.character(x)) x <- structure(as.character(x), names = names(x))
.Internal(grep(as.character(pattern), x, ignore.case, value,
perl, fixed, useBytes, invert))
}
and the use of 'as.character' allows methods to be dispatched (for
example, for factors).
However, for reasons of convenience and also efficiency (as there is
some overhead in using the '.Internal' interface wrapped in a function
closure), the primitive functions are exceptions that can be accessed
directly. And of course, primitive functions are needed for basic
operations--for example '.Internal' is itself a primitive. Note that
primitive functions make no use of R code, and hence are very different
from the usual interpreted functions. In particular, 'formals' and
'body' return 'NULL' for such objects, and argument matching can be
handled differently. For some primitives (including 'call', 'switch',
'.C' and '.subset') positional matching is important to avoid partial
matching of the first argument.
The list of primitive functions is subject to change; currently, it
includes the following.
1. "Special functions" which really are _language_ elements, but
implemented as primitive functions:
{ ( if for while repeat break next
return function quote switch
2. Language elements and basic _operator_s (i.e., functions usually
_not_ called as 'foo(a, b, ...)') for subsetting, assignment,
arithmetic, comparison and logic:
[ [[ $ @
<- <<- = [<- [[<- $<- @<-
+ - * / ^ %% %*% %/%
< <= == != >= >
| || & && !
When the arithmetic, comparison and logical operators are called as
functions, any argument names are discarded so positional matching
is used.
3. "Low level" 0- and 1-argument functions which belong to one of the
following groups of functions:
a. Basic mathematical functions with a single argument, i.e.,
abs sign sqrt
floor ceiling
exp expm1
log2 log10 log1p
cos sin tan
acos asin atan
cosh sinh tanh
acosh asinh atanh
cospi sinpi tanpi
gamma lgamma digamma trigamma
cumsum cumprod cummax cummin
Im Re Arg Conj Mod
'log' is a primitive function of one or two arguments with
named argument matching.
'trunc' is a difficult case: it is a primitive that can have
one or more arguments: the default method handled in the
primitive has only one.
b. Functions rarely used outside of "programming" (i.e., mostly
used inside other functions), such as
nargs missing on.exit interactive
as.call as.character as.complex as.double
as.environment as.integer as.logical as.raw
is.array is.atomic is.call is.character
is.complex is.double is.environment is.expression
is.finite is.function is.infinite is.integer
is.language is.list is.logical is.matrix
is.na is.name is.nan is.null
is.numeric is.object is.pairlist is.raw
is.real is.recursive is.single is.symbol
baseenv emptyenv globalenv pos.to.env
unclass invisible seq_along seq_len
c. The programming and session management utilities
browser proc.time gc.time tracemem retracemem untracemem
4. The following basic replacement and extractor functions
length length<-
class class<-
oldClass oldClass<-
attr attr<-
attributes attributes<-
names names<-
dim dim<-
dimnames dimnames<-
environment<-
levels<-
storage.mode<-
Note that optimizing 'NAMED = 1' is only effective within a
primitive (as the closure wrapper of a '.Internal' will set 'NAMED
= NAMEDMAX' when the promise to the argument is evaluated) and
hence replacement functions should where possible be primitive to
avoid copying (at least in their default methods).
5. The following functions are primitive for efficiency reasons:
: ~ c list
call expression substitute
UseMethod standardGeneric
.C .Fortran .Call .External
round signif rep seq.int
as well as the following internal-use-only functions
.Primitive .Internal
.Call.graphics .External.graphics
.subset .subset2
.primTrace .primUntrace
lazyLoadDBfetch
The multi-argument primitives
call switch
.C .Fortran .Call .External
intentionally use positional matching, and need to do so to avoid
partial matching to their first argument. They do check that the first
argument is unnamed or for the first two, partially matches the formal
argument name. On the other hand,
attr attr<- browser rememtrace substitute UseMethod
log round signif rep seq.int
manage their own argument matching and do work in the standard way.
All the one-argument primitives check that if they are called with a
named argument that this (partially) matches the name given in the
documentation: this is also done for replacement functions with one
argument plus 'value'.
The net effect is that argument matching for primitives intended for
end-user use _as functions_ is done in the same way as for interpreted
functions except for the six exceptions where positional matching is
required.
- Special primitives
- Special internals
- Prototypes for primitives
- Adding a primitive
automatically generated by info2www version 1.2.2.9