.Internal 和 .Primitive在R编译创建时,C代码编译进该系统可以看作“直接的”或通过
.Internal接口实现的。.Internal接口和.External
接口非常类似,除了在语法上。更准确地说,R维持着一个R函数名和
对应的会被调用的C函数的对应表。在习惯上,这些C函数以do_开始并且
返回SEXP。通过这个对应表(文件src/main/names.c内的R_FunTab),
我们可以指定一个函数需要或运行几个参数,在调用前参数是否需要赋值,和是否是
“内部”函数以致需要通过.Internal接口访问或者如.Primitive一样
直接方法且在R里面答应。
R的功能性还可以通过提供对应的C代码然后 加到该函数对应表中来扩充。
通常,这类函数使用 .Internal() 接口,因为这样做比较
安全,特别是允许透明地处理命名的和默认的参数。例如,
axis 如下定义
axis <- function(side, at = NULL, labels = NULL, ...)
.Internal(axis(side, at, labels, ...))
但是,出于便利和效率考虑(还因为在一个函数闭包里面用.Internal
接口有一些限制),有些函数可以直接访问。注意,
这些函数不用 R 代码,因此
和通常的解释型函数差别很大。特别是,
args,formals 和 body
对这些对象返回 NULL,并且参数匹配完全基于位置
(空位置的会被抛弃)。
这些 “原始” 函数的列表常常会改变: 现在,它包括如下一些函数。
{ ( if for while repeat break next
return function quote on.exit
foo(a, b, ...)这样的函数看待)。
这些是如下的1-,2-,和N-参数函数:
[ [[ $ @
<- <<- = [<- [[<- $<-
+ - * / ^ %% %*% %/%
< <= == != >= >
| || & && !
sign abs
floor ceiling trunc
sqrt exp
cos sin tan
acos asin atan
cosh sinh tanh
acosh asinh atanh
cumsum cumprod cummax cummin
Im Re Arg Conj Mod
注意,R 函数 log有个可选的命名参数
base,因此定义如下,
log <- function(x, base = exp(1)) {
if(missing(base))
.Internal(log(x))
else
.Internal(log(x, base))
}
这样保证了 log(x = pi, base = 2) 和
log(base = 2, x = pi)完全一样。
nargs missing
interactive is.xxx
.Primitive .Internal
globalenv baseenv emptyenv pos.to.env
unclass
seq_along seq_len
(其中xxx表示27个不同的概念,如
function, vector, numeric等等,但不是
is.loaded)。
debug undebug browser proc.time gc.time
length length<-
class class<-
oldClass oldCLass<-
attr attr<-
attributes attributes<-
names names<-
dim dim<-
dimnames dimnames<-
environment<-
levels<-
注意,优化 NAMED = 1 仅仅在原始函数中有效
(因为.Internal的闭包会在参数中设置NAMED = 2),因此
替换函数必须是原始函数(如果可能)以避免拷贝(至少在它们默认的方法中)。
: ~ c list
call as.call as.character
expression substitute as.environment
UseMethod invisible standardGeneric
.C .Fortran .Call .External
.Call.graphics .External.graphics
.subset .subset2 .primTrace .primUntrace
tracemem retracemem untracemem
rep seq.int
rep 和 seq.int 管理它们自己的参数匹配并且以标准方式工作。