迭代S4对象槽Rcpp

Rom*_*kyi 4 r rcpp

是否可以迭代S4对象槽?

到目前为止,我能够想出这个.但我真的想避免调用R函数slotNames.是否有可能在C/C++级别上做同样的事情?

// [[Rcpp::export]]
void foo(SEXP x) {
  Rcpp::S4 obj(x);
  Function slotNames("slotNames"); 
  CharacterVector snames = slotNames(obj);
  for (int i = 0; i < snames.size(); i++) {
    SEXP slot = obj.slot(Rcpp::as<std::string>(snames[i]));
    // do something with slot
  }
}
Run Code Online (Sandbox Code Playgroud)

Kev*_*hey 6

看看R源代码,我看到这样的东西:

/**
 * R_has_slot() : a C-level test if a obj@<name> is available;
 *                as R_do_slot() gives an error when there's no such slot.
 */
int R_has_slot(SEXP obj, SEXP name) {

#define R_SLOT_INIT                         \
    if(!(isSymbol(name) || (isString(name) && LENGTH(name) == 1)))  \
    error(_("invalid type or length for slot name"));       \
    if(!s_dot_Data)                         \
    init_slot_handling();                       \
    if(isString(name)) name = installChar(STRING_ELT(name, 0))

    R_SLOT_INIT;
    if(name == s_dot_Data && TYPEOF(obj) != S4SXP)
    return(1);
    /* else */
    return(getAttrib(obj, name) != R_NilValue);
}
Run Code Online (Sandbox Code Playgroud)

我想,这意味着你可以将其拖出来getAttrib.

所以,今天我了解到S4插槽实际上只是特殊属性,可以使用这些属性@.注意:

> setClass("Foo", list(apple = "numeric"))
> foo <- new("Foo", apple = 1)
> foo@apple
[1] 1
> attributes(foo)
$apple
[1] 1

$class
[1] "Foo"
attr(,"package")
[1] ".GlobalEnv"

> foo@class
[1] "Foo"
attr(,"package")
[1] ".GlobalEnv"
> attr(foo, "bar") <- 2
> foo@bar
[1] 2
Run Code Online (Sandbox Code Playgroud)

希望这至少为您提供了一个入门的地方.