假设我有一个以SEXP
类型为参数的函数:
SEXP myFun(SEXP param)
如何找出此参数的类型?查看调试器中的SEXP
类型,我可以看到我可以调用param->sxpinfo.type
来获取SEXPTYPE
的数字表示。从快速浏览一下,它们似乎与这些匹配:
no SEXPTYPE Description 0 NILSXP NULL 1 SYMSXP symbols 2 LISTSXP pairlists 3 CLOSXP closures 4 ENVSXP environments 5 PROMSXP promises 6 LANGSXP language objects 7 SPECIALSXP special functions 8 BUILTINSXP builtin functions 9 CHARSXP internal character strings 10 LGLSXP logical vectors 13 INTSXP integer vectors 14 REALSXP numeric vectors 15 CPLXSXP complex vectors 16 STRSXP character vectors 17 DOTSXP dot-dot-dot object 18 ANYSXP make “any” args work 19 VECSXP list (generic vector) 20 EXPRSXP expression vector 21 BCODESXP byte code 22 EXTPTRSXP external pointer 23 WEAKREFSXP weak reference 24 RAWSXP raw vector 25 S4SXP S4 classes not of simple type
(来源:http://www.biosino.org/R/R-doc/R-ints/SEXPTYPEs.html#SEXPTYPEs)
但这看起来很糟糕。检查SEXP
变量类型的正确方法是什么?
答案 0 :(得分:5)
使用R API,TYPEOF
宏用于获取运行时类型。我们可以看到来自Rinternals.h
的一些相关位(有趣的是,不是编码为enum
,而是作为一系列宏定义;假设是为了向后兼容一些非常糟糕的编译器一些非常糟糕的平台...)
typedef unsigned int SEXPTYPE;
#define NILSXP 0 /* nil = NULL */
#define SYMSXP 1 /* symbols */
#define LISTSXP 2 /* lists of dotted pairs */
#define CLOSXP 3 /* closures */
#define ENVSXP 4 /* environments */
#define PROMSXP 5 /* promises: [un]evaluated closure arguments */
#define LANGSXP 6 /* language constructs (special lists) */
#define SPECIALSXP 7 /* special forms */
#define BUILTINSXP 8 /* builtin non-special forms */
#define CHARSXP 9 /* "scalar" string type (internal only)*/
#define LGLSXP 10 /* logical vectors */
/* 11 and 12 were factors and ordered factors in the 1990s */
#define INTSXP 13 /* integer vectors */
#define REALSXP 14 /* real variables */
#define CPLXSXP 15 /* complex variables */
#define STRSXP 16 /* string vectors */
#define DOTSXP 17 /* dot-dot-dot object */
#define ANYSXP 18 /* make "any" args work.
Used in specifying types for symbol
registration to mean anything is okay */
#define VECSXP 19 /* generic vectors */
#define EXPRSXP 20 /* expressions vectors */
#define BCODESXP 21 /* byte code */
#define EXTPTRSXP 22 /* external pointer */
#define WEAKREFSXP 23 /* weak reference */
#define RAWSXP 24 /* raw bytes */
#define S4SXP 25 /* S4, non-vector */
/* used for detecting PROTECT issues in memory.c */
#define NEWSXP 30 /* fresh node creaed in new page */
#define FREESXP 31 /* node released by GC */
#define FUNSXP 99 /* Closure or Builtin or Special */
如果定义了USE_RINTERNALS
,我们可以看到R在SEXPTYPE
中查询:
#define TYPEOF(x) ((x)->sxpinfo.type)
这正如你所说的那样:)但在大多数情况下(即 - 除非你知道你正在做什么),你不应该使用#define
,所以定义来自memory.c:
int (TYPEOF)(SEXP x) { return TYPEOF(CHK(x)); }
...只是调用TYPEOF
宏,但使用CHK
来确保SEXP
它已经不受保护{\ n}}
浏览R源(并且一定要查看R.h
和Rinternals.h
)以了解R API中实际暴露的内容及其使用方式非常有用
也就是说,R API是一个丑陋的野兽,所以我们确实建议使用Rcpp
,它提供了许多很好的类,它们包裹SEXP
但提供编译时类型和一系列有用的函数来使用/操作它们。请参阅@ eddelbuettel' s Rcpp page作为介绍,the Rcpp Gallery例如使用Rcpp。