rlh2 rlh2 - 13 days ago 5
R Question

Is it possible to access R's primitive "class" function via Rcpp?

I am trying loop through an R list and extract the primary class (defined as the first element in the case of an S3 class) of each R object in the list. I know it is possible to call a generic R function from Rcpp, but I would like to avoid doing that. The reason I am pursuing this to begin with is for performance.

I saw another question here regarding access to R's primitive functions:
use primitive functions in Rcpp and it looks like Rcpp's sugar expressions solved that particular issue, but it doesn't look like 'class' is available in Rcpp sugar.

I know that one can access attributes in Rcpp (which is how S3 classes are stored) and I also know that S4 objects are detectable in Rcpp, so I think there is probably a way to do this, but it would be easiest of the primitive class function were directly callable and I am just missing something.

library(Rcpp)

objList <- list(
a = 10,
b = lm(mpg~cyl, data = mtcars),
c = glm(mpg~cyl, data = mtcars, family = gaussian)
)
##R approach
primaryClass <- function(x){
class(x)[1]
}

vapply(objList, primaryClass, character(1))

##Rcpp skeleton approach
cppFunction('CharacterVector primaryClass(List x) {
int nrow = x.size();
CharacterVector out(nrow);
for (int i = 0; i < nrow; i++) {
out[i] = "classHere";
}
return out;
}')

primaryClass(objList)

Answer

Not everything that R "has" internally is available to Rcpp. There is certainly no automatic mechanism (which is why the answer on max() you refer show different but equivalent max() functions).

But you can look at the class attribute (which covers S3):

R> cppFunction('std::string getClass(RObject x) { 
+      if (x.hasAttribute("class")) return x.attr("class"); else return ""; }')
R> getClass(lm.D9)         # after running `example(lm)` to get `lm.D9`
[1] "lm"
R> getClass(2.345)
[1] ""
R>

Similarly you can test for the other object types and add logic.