Pairlists are linked lists used for calls, unevaluated arguments, attributes, and in ...
.
Rboolean Rf_isPairList(SEXP); // LISTSXP
Rboolean Rf_isLanguage(SEXP); // LANGSXP
Rboolean Rf_isList(SEXP); // LISTSXP, NILSXP
The terminology of pairlist comes from LISPs "dotted pairs" which is a way of describing "CONS" cells. A CONS cell is a pair of pointers:
- "CAR" (contents of address register) points to an object
- "CDR" (contents of decrement register) points to the next element in the list.
The CDR of the last element is
R_NilValue
.
Graphically, this looks like:
To loop over all elements of a pairlist, use this template:
int length(SEXP s) {
int i = 0;
for(SEXP cons = x; cons != R_NilValue; cons = CDR(nxt) {
SEXP el = CAR(cons);
i++;
}
return i;
}
SEXP Rf_cons(SEXP a, SEXP b) // function arguments
SEXP Rf_lcons(SEXP a, SEXP b) // calls
The CDR
of the final value must be R_NilValue
.
There are helpers for 5-6 arguments. These automatically add the terminating R_NilValue
.
SEXP Rf_list1(SEXP x1);
SEXP Rf_list2(SEXP x1, SEXP x2);
SEXP Rf_list3(SEXP x1, SEXP x2, SEXP x3);
SEXP Rf_list4(SEXP x1, SEXP x2, SEXP x3, SEXP x4);
SEXP Rf_list5(SEXP x1, SEXP x2, SEXP x3, SEXP x4, SEXP x5);
SEXP Rf_lang1(SEXP x1);
SEXP Rf_lang2(SEXP x1, SEXP x2);
SEXP Rf_lang3(SEXP x1, SEXP x2, SEXP x3);
SEXP Rf_lang4(SEXP x1, SEXP x2, SEXP x3, SEXP x4);
SEXP Rf_lang5(SEXP x1, SEXP x2, SEXP x3, SEXP x4, SEXP x5);
SEXP Rf_lang6(SEXP x1, SEXP x2, SEXP x3, SEXP x4, SEXP x5, SEXP x6);
SEXP Rf_allocFormalsList2(SEXP x1, SEXP x2);
SEXP Rf_allocFormalsList3(SEXP x1, SEXP x2, SEXP x3);
SEXP Rf_allocFormalsList4(SEXP x1, SEXP x2, SEXP x3, SEXP x4);
SEXP Rf_allocFormalsList5(SEXP x1, SEXP x2, SEXP x3, SEXP x4, SEXP x5);
SEXP Rf_allocFormalsList6(SEXP x1, SEXP x2, SEXP x3, SEXP x4, SEXP x5, SEXP x6);
SEXP Rf_PairToVectorList(SEXP x);
SEXP Rf_VectorToPairList(SEXP x);
SEXP Rf_listAppend(SEXP source, SEXP target);
Unlike lists (VECSXP
s), pairlists (LISTSXP
s) have no way to index into an arbitrary location. Instead, R provides a set of helper functions that navigate along a linked list. The basic helpers are CAR()
, which extracts the first element of the list, and CDR()
, which extracts the rest of the list. These can be composed to get CAAR()
, CDAR()
, CADDR()
, CADDDR()
, and so on. Corresponding to the getters, R provides setters SETCAR()
, SETCDR()
, etc.
SEXP CAR(SEXP e);
SEXP CDR(SEXP e);
SEXP CAAR(SEXP e);
SEXP CDAR(SEXP e);
SEXP CADR(SEXP e);
SEXP CDDR(SEXP e);
SEXP CDDDR(SEXP e);
SEXP CADDR(SEXP e);
SEXP CADDDR(SEXP e);
SEXP CAD4R(SEXP e);
SEXP SETCAR(SEXP x, SEXP y);
SEXP SETCDR(SEXP x, SEXP y);
SEXP SETCADR(SEXP x, SEXP y);
SEXP SETCADDR(SEXP x, SEXP y);
SEXP SETCADDDR(SEXP x, SEXP y);
SEXP SETCAD4R(SEXP e, SEXP y);
void SET_TAG(SEXP x, SEXP y);
SEXP (TAG)(SEXP e);
// CONS with no-refcounting ?
SEXP CONS_NR(SEXP a, SEXP b);
// Used for missing values in function calls?
int (MISSING)(SEXP x);
void (SET_MISSING)(SEXP x, int v);
Some functions allow you to work with a pair list as if it's a vector:
SEXP Rf_allocList(int n); # create new pairlist of specified length
SEXP Rf_nthcdr(SEXP, int); # access nth element
If you use these it's easy to get O(n^2) behaviour, but for the usual size of pairlists, this is unlikely to cause a performance bottleneck.
Pairlists are most commonly used for function calls. Calls to functions with 0 to 5 arguments can be created directly via Rf_lang1()
to Rf_lang6()
. However, these functions do not allow for named arguments. If you need named arguments, use the following template:
// equivalent of:
// fun(arg1 = a, arg2 = b, arg3 = c)
SEXP call = PROTECT(Rf_allocVector(LANGSXP, 4)); // 4 = # of args + 1
SETCAR(call, fun);
SEXP s = CDR(call);
SETCAR(s, a);
SET_TAG(s, Rf_install("arg1"));
s = CDR(s);
SETCAR(s, b);
SET_TAG(s, Rf_install("arg2"));
s = CDR(s);
SETCAR(s, c);
SET_TAG(s, Rf_install("arg3"));
SEXP out = PROTECT(Rf_eval(call, env));
...
UNPROTECT(2);
Represents the ...
structure in R. Easiest to get to with findVar(R_DotsSymbol, env)
or similar. Is usually a pair list, but will have value R_MissingArg
if there are no arguments.
There is a single value with type NILSXP
: R_NilValue
. This corresponds to NULL
in R, and is often used as generic zero length vector.
SEXP Rf_getAttrib(SEXP x, SEXP symbol);
SEXP Rf_setAttrib(SEXP x, SEXP symbol, SEXP value);
// Copies attributes except names, dim, and dimnames
void Rf_copyMostAttrib(SEXP source, SEXP target);
// Get the pairlist containing the attributes
SEXP (ATTRIB)(SEXP x);
void SET_ATTRIB(SEXP x, SEXP v);
void DUPLICATE_ATTRIB(SEXP to, SEXP from);
void SHALLOW_DUPLICATE_ATTRIB(SEXP to, SEXP from);