R语言经典问答:深入领略.Internal函数
当前位置:以往代写 > 其他教程 >R语言经典问答:深入领略.Internal函数
2019-06-14

R语言经典问答:深入领略.Internal函数

R语言经典问答:深入领略.Internal函数

写R语言的书,许多城市提到一个汗青话题,就是“Scheme和R语言的干系”。也有许多人问过我,R毕竟那边受了Scheme可能Lisp影响。这个提问也正好提供了一个很好的例子。

提问原帖:Understanding how .Internal C functions are handled in R

 

“黑邪术”

本日咱们从set.seed()函数的源代码(如下所示)聊起。

可以明明看到提前界说的宏(checkArity、CADR、CADDR等)和函数的四个参数(call、op、args和env),卖力正利用的时候,set.seed()貌似只有一个参数,好比set.seed(1)。

那这些“黑邪术”毕竟是做什么的。

SEXP attribute_hidden do_setseed (SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP skind, nkind;
    int seed;

    checkArity(op, args);
    if(!isNull(CAR(args))) {
	seed = asInteger(CAR(args));
	if (seed == NA_INTEGER)
	    error(_("supplied seed is not a valid integer"));
    } else seed = TimeToSeed();
    skind = CADR(args);
    nkind = CADDR(args);
    GetRNGkind(R_NilValue); /* pull RNG_kind, N01_kind from 
			       .Random.seed if present */
    if (!isNull(skind)) RNGkind((RNGtype) asInteger(skind));
    if (!isNull(nkind)) Norm_kind((N01type) asInteger(nkind));
    RNG_Init(RNG_kind, (Int32) seed); /* zaps BM history */
    PutRNGstate();
    return R_NilValue;
}

checkArity和op

先说checkArity,checkArity通过挪用Rf_checkArityCall来查抄函数的参数个数是否和预设的相符。

那预设又在哪儿呢??

是打开R源代码的时候了,在文件/src/main/names.c的开头,有这样一个段注释。这里只截取了很小的一段,更完整的各人照旧打开源代码本身看吧。

留意个中几列的名字:printname是函数名,就是我们在R里直接利用的函数名;c-entry,这个是挪用的C函数名,offset是个指
针,就是谁人op参数,由.Internal和.Primitive挪用的函数,每个都有的一个offset;arity,这个就是
checkArity来查抄的参数个数。

/* Table of  .Internal(.) and .Primitive(.)  R functions
 * =====     =========        ==========
 * Each entry is a line with
 *
 *  printname  c-entry     offset  eval  arity   pp-kind   precedence  rightassoc
 *  ---------  -------     ------  ----  -----   -------   ----------  ----------
{"colSums",    do_colsum,  0,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"colMeans",   do_colsum,  1,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowSums",    do_colsum,  2,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowMeans",   do_colsum,  3,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},

但这好像照旧很奇怪,好比rowSums,纵然查辅佐文档,参数个数也不外三个,但它对应的arity是4。这个问题照旧要看源代码办理。

> rowSums
function (x, na.rm = FALSE, dims = 1L) 
{
    if (is.data.frame(x)) 
        x <- as.matrix(x)
    if (!is.array(x) || length(dn <- dim(x)) < 2L) 
        stop("'x' must be an array of at least two dimensions")
    if (dims < 1L || dims > length(dn) - 1L) 
        stop("invalid 'dims'")
    p <- prod(dn[-(1L:dims)])
    dn <- dn[1L:dims]
    z <- if (is.complex(x)) 
        .Internal(rowSums(Re(x), prod(dn), p, na.rm)) + (0+1i) * 
            .Internal(rowSums(Im(x), prod(dn), p, na.rm))
    else .Internal(rowSums(x, prod(dn), p, na.rm))
    if (length(dn) > 1L) {
        dim(z) <- dn
        dimnames(z) <- dimnames(x)[1L:dims]
    }
    else names(z) <- dimnames(x)[[1L]]
    z
}

撤除前面的参数处理惩罚,真正轮到.Internal挪用rowSums时,简直是4个参数。

.Internal(rowSums(Re(x), prod(dn), p, na.rm))

call、args和env

这三个从名字上也较量容易猜出来是做什么的

args是“真正”的参数,就是我们在利用set.seed()时,赋给函数的参数

call是完整挪用,留着被match.call()捕捉

env是函数挪用情况。

CAR和CDR

其实这俩才是真正的“黑邪术”,也正是R受到Lisp影响的重要浮现。

陈腐的pairlist

R语言里有一种很陈腐并且鲜为人知的数据范例,Pairlist。

说陈腐,是因为pairlist担任自Lisp,可以一直追溯到IBM
704电脑,Lisp降生的时代;说鲜为人知,是因为正常写R剧本,能遇到这玩意的几率太低了。险些只有.Options还能遇到,但用.Options
的人也没几个呀。CAR和CDR就是操纵这种上古数据布局的。

Lisp的CAR和CDR

CAR = Contents of the Address part of Register number

CDR = Contents of the Decrement part of Register number

我感受正凡人应该很难领略毕竟是什么意思,会用Lisp的大神请自觉封锁欣赏器。

#p#分页标题#e#

这么说吧,cons是Lisp各类方言里最根基的函数,和C++里的结构器的观念雷同,用于结构pairlist,好比( cons x y
)。而pairlist又是Lisp里最根基的数据布局,可以搭建更巨大的对象,好比一个链表就可以这么来(cons 42 (cons 69
(cons 613 nil))),具体内容请磨练维基百科。

car和cdr就是对cons单位的最根基操纵,好比( car ( cons x y ) )就是取cons单位的第一个元素x,( cdr ( cons x y ) )就是取第二个元素y。

R底层的代码常常呈现的CAR和CDR就是对Lisp的保存,R受Lisp影响的重要浮现。

CAD4R和CARR

但仅仅保存CAR和CDR好像还不能浮现R受Lisp影响之深,Writing R Extension里用到的CAD4R才是精华呀。

在Lisp里,(cadr ‘(1 2 3))和(car (cdr ‘(1 2 3)))是等价的,雷同地(caar ‘((1 2) (3 4)))和(car (car ‘((1 2) (3 4))))是等价的。

所以在R内里CAAR(x)和CAR(CAR(x))是等价的,CADDR(x)和CAR(CDR(CDR(x))是等价的,谁人CAD4R就是CADDDDR,一共有4个CDR操纵。

假如这都不敷够让你以为R深受Lisp影响,那我也就真的没辙了。

 

 

 

 

本文转载自:http://thirdwing.github.io/2013/11/24/internal/

    关键字:

在线提交作业