是否可以通过 Rcpp 访问 R 的原始 "class" 函数?

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

我正在尝试遍历 R 列表并提取列表中每个 R 对象的主要 class(在 S3 class 的情况下定义为第一个元素)。我知道可以从 Rcpp 调用通用 R 函数,但我想避免这样做。我开始追求这个的原因是为了性能。

我在这里看到另一个关于访问 R 的原始函数的问题: use primitive functions in Rcpp 看起来 Rcpp 的 sugar 表达式解决了那个特定问题,但看起来 'class' 在 Rcpp sugar 中不可用。

我知道可以访问 Rcpp 中的属性(这是 S3 classes 的存储方式)而且我也知道 S4 对象在 Rcpp 中是可检测的,所以我认为可能有一种方法可以做到这个,但最简单的原始 class 函数是可直接调用的,我只是遗漏了一些东西。

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)

并非 R "has" 内部的所有内容都可用于 Rcpp。肯定没有自动机制(这就是为什么您引用的 max() 上的答案显示不同但等效的 max() 函数)。

但是您可以查看class属性(涵盖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>

同样,您可以测试其他对象类型并添加逻辑。