c - pairs - poligono en r
Comprender cómo. Las funciones internas C se manejan en R (2)
Las funciones básicas de extracción de paleta C-level son CAR
y CDR
. (Las listas de parejas son muy similares a las listas, pero se implementan como una lista vinculada y se usan internamente para las listas de argumentos). Tienen equivalentes R simples: x[[1]]
x[-1]
. R también proporciona muchas combinaciones de los dos:
-
CAAR(x) = CAR(CAR(x))
que es equivalente ax[[1]][[1]]
-
CADR(x) = CAR(CDR(x))
que es equivalente ax[-1][[1]]
, es decir,x[[2]]
-
CADDR(x) = CAR(CDR(CDR(x))
es equivalente ax[-1][-1][[1]]
, es decir,x[[3]]
- y así
Acceder al enésimo elemento de una pairlist es una operación O(n)
, a diferencia del acceso al enésimo elemento de una lista que es O(1)
. Es por eso que no hay funciones más agradables para acceder al enésimo elemento de una pairlist.
Las funciones internas / primitivas no hacen coincidir por nombre, solo usan la coincidencia de posición, por lo que pueden usar este sistema simple para extraer los argumentos.
A continuación, debe comprender cuáles son los argumentos para la función C. No estoy seguro de dónde están documentados, por lo que podría no estar completamente en lo cierto sobre la estructura, pero debería ser las piezas generales:
call
: la llamada completa, como podría ser capturada pormatch.call()
op
: el índice de la función .Interna llamada desde R. Esto es necesario porque hay una asignación de muchos a uno desde. Funciones internas a funciones C. (por ejemplo,do_summary
implementa sum, mean, min, max y prod). El número es la tercera entrada ennames.c
- siempre es 0 parado_setseed
y, por lo tanto, nunca se usaargs
: una lista de pares de los argumentos suministrados a la función.env
: el entorno desde el que se llamó a la función.
checkArity
es una macro que llama a Rf_checkArityCall
, que básicamente busca el número de argumentos (la quinta columna en names.c
es names.c
) y se asegura de que el número suministrado coincida. Tienes que seguir algunas macros y funciones en C para ver qué está sucediendo; es muy útil tener una copia local de R-source por la que puedas pasar.
Me pregunto si alguien me puede ilustrar cómo R ejecuta una llamada C
desde un comando R escrito en el indicador de la consola. Estoy particularmente confundido por el tratamiento de R
de a) los argumentos de la función yb) la llamada a la función en sí misma.
Tomemos un ejemplo, en este caso set.seed()
. Preguntándose cómo funciona. Tecleo el nombre en el prompt, obtengo la fuente ( mire aquí para más información sobre eso ), vea que eventualmente hay un .Internal(set.seed(seed, i.knd, normal.kind)
, tan diligentemente busca el nombre de la función relevante en la sección .Internals
de /src/names.c
, encuentra que se llama do_setseed
y está en RNG.c
que me lleva a ...
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;
}
- ¿Qué son
CAR
,CADR
,CADDR
? Mi investigación me lleva a creer que son una construcción influenciada porLisp
en relación con las listas, pero más allá de eso no entiendo qué hacen estas funciones ni por qué son necesarias . - ¿Qué hace
checkArity()
? -
SEXP args
parece explicarse por sí mismo, pero ¿es esta una lista de los argumentos que se pasan en la llamada a la función? - ¿Qué representa
SEXP op
? Tomo esto para decir operador (como en funciones binarias como+
), pero ¿para qué sirve laSEXP call
?
¿Alguien puede pasar por lo que sucede cuando escribo?
set.seed(1)
en el prompt de la consola R, hasta el punto en que se definen skind
y nkind
? Encuentro que no puedo entender bien el código fuente en este nivel y la ruta desde el intérprete hasta la función C.
CAR
y CDR
son la forma de acceder a los objetos de Pairlist, como se explica en la sección 2.1.11 de R Language Definition . CAR
contiene el primer elemento y CDR
contiene los elementos restantes. Un ejemplo se da en la sección 5.10.2 de Writing R Extensions :
#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);
También hay una macro TAG
para acceder a los nombres dados a los argumentos reales.
checkArity
asegura que la cantidad de argumentos pasados a la función es correcta. args
son los argumentos reales pasados a la función. op
es un puntero de desplazamiento "utilizado para funciones C que tratan con más de una función R" (citado de src/main/names.c
, que también contiene la tabla que muestra el desplazamiento y la aridad de cada función).
Por ejemplo, do_colsum
maneja col/rowSums
y 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}},
Tenga en cuenta que arity
en la tabla anterior es 4 porque (aunque rowSums
et al solo tienen 3 argumentos) do_colsum
tiene 4, que puede ver desde la llamada rowSums
en 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
}