Sim*_*lon 39 c syntax r internals
我想知道是否有人可以向我说明R如何C从控制台提示符下键入的R命令执行调用.我R对a)函数参数的处理和b)函数调用本身特别困惑.
在这种情况下,我们举一个例子set.seed().想知道它是如何工作我在提示符下键入名称,获得源(看看这里的更多介绍),看到有最后一个.Internal(set.seed(seed, i.knd, normal.kind),所以尽职尽责地在查找相关的函数名.Internals的部分/src/names.c,发现它被称为do_setseed是在RNG.c哪导致我......
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);
//...
//DO RNG here
//...
return R_NilValue;
}
Run Code Online (Sandbox Code Playgroud)
CAR,CADR,CADDR?我的研究让我相信它们是一个Lisp有关列表的受影响的结构,但除此之外,我不明白这些功能的作用或为什么需要它们.checkArity()办?SEXP args 似乎是自解释的,但这是函数调用中传递的参数列表吗?SEXP op代表?我认为这意味着运算符(比如二进制函数+),但那么它是什么SEXP call?是否有人能够流经我打字时发生的事情
set.seed(1)
Run Code Online (Sandbox Code Playgroud)
在R控制台提示,直至在该点skind和nkind被定义?我发现我无法很好地理解这个级别的源代码以及从解释器到C函数的路径.
Jos*_*ich 23
CAR以及CDR如何访问pairlist对象,如R语言定义的 2.1.11节所述. CAR包含第一个元素,并CDR包含其余元素.编写R扩展的第5.10.2节给出了一个例子:
#include <R.h>
#include <Rinternals.h>
SEXP convolveE(SEXP args)
{
int i, j, na, nb, nab;
double *xa, *xb, *xab;
SEXP a, b, ab;
a = PROTECT(coerceVector(CADR(args), REALSXP));
b = PROTECT(coerceVector(CADDR(args), REALSXP));
...
}
/* The macros: */
first = CADR(args);
second = CADDR(args);
third = CADDDR(args);
fourth = CAD4R(args);
/* provide convenient ways to access the first four arguments.
* More generally we can use the CDR and CAR macros as in: */
args = CDR(args); a = CAR(args);
args = CDR(args); b = CAR(args);
Run Code Online (Sandbox Code Playgroud)
还有一个TAG宏来访问给实际参数的名称.
checkArity确保传递给函数的参数数量是正确的.args是传递给函数的实际参数.op是偏移指针"用于处理多个R函数的C函数"(引自src/main/names.c,其中还包含显示每个函数的偏移和arity的表).
例如,do_colsum句柄col/rowSums和col/rowMeans.
/* 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}},
Run Code Online (Sandbox Code Playgroud)
请注意,arity上表中的4是因为(尽管rowSumset al只有3个参数)do_colsum有4个,您可以从.Internal调用中看到rowSums:
> 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
}
Run Code Online (Sandbox Code Playgroud)
had*_*ley 19
基本的C级pairlist提取功能是CAR和CDR.(Pairlists与列表非常相似,但是作为链表实现,并在内部用于参数列表).他们有简单的R等价物:x[[1]]和x[-1].R还提供了两者的许多组合:
CAAR(x) = CAR(CAR(x)) 这相当于 x[[1]][[1]]CADR(x) = CAR(CDR(x))相当于x[-1][[1]],即x[[2]]CADDR(x) = CAR(CDR(CDR(x))相当于x[-1][-1][[1]],即x[[3]]访问pairlist的第n个元素是一个O(n)操作,不像访问列表的第n个元素O(1).这就是为什么没有更好的功能来访问pairlist的第n个元素.
内部/原始函数不按名称进行匹配,它们仅使用位置匹配,这就是为什么它们可以使用这个简单的系统来提取参数.
接下来,您需要了解C函数的参数是什么.我不确定这些文件在哪里记录,所以我可能不完全正确的结构,但我应该是一般的部分:
call:完整的呼叫,可能被捕获 match.call()
op:从R调用的.Internal函数的索引.这是必需的,因为从.Internal函数到C函数有多对一的映射.(例如do_summary实现sum,mean,min,max和prod).这个数字是第三个条目names.c- 它始终为0 do_setseed,因此从未使用过
args:提供给函数的参数的一对列表.
env:调用函数的环境.
checkArity是一个调用的宏Rf_checkArityCall,它基本上查找参数的数量(names.carity中的第五列),并确保提供的数字匹配.你必须在C中完成相当多的宏和函数才能看到正在发生的事情 - 拥有一个你可以通过的R源的本地副本是非常有帮助的.
| 归档时间: |
|
| 查看次数: |
1437 次 |
| 最近记录: |