3

inline我写了一个简单的 C 函数在 R 中使用,它应该接受任何对象并返回该对象类。我试图遵循Writing R Extensions手册,其中指出

getAttriband函数获取和setAttrib设置单个属性。他们的第二个参数是SEXP在我们想要的属性的符号表中定义名称;这些和许多这样的符号在头文件中定义Rinternals.h

此外它还指出..

在 R 中,这class只是命名的属性"class",因此可以这样处理。

所以我写了这个...

#  required package
require( inline )

#  Simple C function to get "class" attribute of an R object
classC <- cfunction( c(x = "ANY") , '

  SEXP out;
  PROTECT(out = allocVector(STRSXP, 1));
  SET_STRING_ELT(out, 0, mkChar("class"));
  UNPROTECT(1);
  return  getAttrib(x, out) ;

')

但是在各种不同类的 R 对象上测试它有时会返回class,但通常会返回NULL。我看不到它所处理的对象类型之间的联系所以不确定我哪里出错了......

#  Various classes of objects
con <- file("text.txt")
d <- data.frame( a = 1 )
e <- new.env()
f <- y ~ 1
fun <- function(x) x^2
i <- 1L:10L
l <- list( 1 , 2 , 3 )
m <- matrix( 1 , 10 , 10 )
n <- runif(1)
v <- 1:10

并运行我得到的功能......

#  Output from the function
classC(con)
#[1] "file"       "connection"
classC(d)
#[1] "data.frame"
classC(e)
#NULL
classC(f)
#[1] "formula"
classC(fun)
NULL
classC(i)
NULL
classC(l)
#NULL
classC(m)
#NULL
classC(n)
#NULL
classC(v)
#NULL

我错过了什么?我很感兴趣,因为我最终想编写一个小辅助函数,它返回一个globalenvironment包含特定class. 但主要是为了我自己的好奇心和学习,我知道我可以做类似的事情:

sapply( ls() , function(x) class( get( x ) ) )
4

1 回答 1

3

文档位于 :) 你所做的相当于 R 函数:

classR = function(x) attributes(x)$class

当您打电话时,R 会执行class以下操作:

SEXP R_data_class(SEXP obj, Rboolean singleString)
{
    SEXP value, klass = getAttrib(obj, R_ClassSymbol);
    int n = length(klass);
    if(n == 1 || (n > 0 && !singleString))
        return(klass);
    if(n == 0) {
        SEXP dim = getAttrib(obj, R_DimSymbol);
        int nd = length(dim);
        if(nd > 0) {
            if(nd == 2)
                klass = mkChar("matrix");
            else
                klass = mkChar("array");
        }
        else {
          SEXPTYPE t = TYPEOF(obj);
          switch(t) {
          case CLOSXP: case SPECIALSXP: case BUILTINSXP:
            klass = mkChar("function");
            break;
          case REALSXP:
            klass = mkChar("numeric");
            break;
          case SYMSXP:
            klass = mkChar("name");
            break;
          case LANGSXP:
            klass = lang2str(obj, t);
            break;
          default:
            klass = type2str(t);
          }
        }
    }
    else
        klass = asChar(klass);
    PROTECT(klass);
    value = ScalarString(klass);
    UNPROTECT(1);
    return value;
}

所以你可以看到它对你得到的所有情况进行了一堆检查NULL

一个简单的选择是class从您的函数中调用:

eval(lang2(install("class"), x), R_GlobalEnv)
于 2013-10-30T16:44:21.017 回答