[Rcpp-devel] Filling a list with iterator, or setting names from CharacterVector/SEXP?

Christian Gunning xian at unm.edu
Fri Sep 7 09:32:41 CEST 2012


> | Can I use as<std::string>() and then iterate over the CharacterVector?
>
> Sure, works via   Rcpp::as< std::vector< std::string> >(foo)

Perfect, thanks.  Revised example included below for reference.

> I am not sure what it is that you want but if you look e.g. at RcppExamples
> and its examples related to parameter passage in and out, you see that we can
> pick _arbitrary_ objects in and out of Rcpp::Lists by name.   Does that help?

It looks like I just answered my own question -- I'd like to get the
actual *names* of the list on the C++ side:
Rcpp::List listnames = mylist.attr("names");
Is the .attr mechanism general to any named attribute that belongs to an SEXP?

The ultimate goal is C++ error-checking of list-access names -- if the
named element is not present in the list, print the offending name and
throw an exception.  Is there an easier way to do this than checking
the supplied name (as std::string) against the vector of list names?
I admit this looks convoluted, but it's a minimal example...

using namespace Rcpp ;
class World {
    public:
        World(SEXP mymat_) : mymat(mymat_), myrows(0), mycols(0) {
            Rcpp::List mynames = mymat.attr("dimnames");
            CharacterVector rownames_ = mynames[0];
            rownames = Rcpp::as< std::vector< std::string>
>(rownames_);
            nrows = rownames.size();
            for (int i=0; i<nrows; i++) {
                       myrows[rownames[i]] = i;
            }
            rownames_list = myrows.attr("names");
        }
        SEXP get(std::string varname) {
            if (debug) {
                // check that varname is in rownames_list
            }
            return myrows[varname];
       }
       void put(std::string varname, int val){
            if (debug) {
                // check that varname is in rownames_list
            }
            myrows[varname] = val;
        };
    public:
        Rcpp::List myrows, mycols;
    private:
        std::vector<std::string> rownames;
        Rcpp::List rownames_list ;
        Rcpp::NumericMatrix mymat;
        Rcpp::List mynames;
        int  nrows, ncols;
        bool debug;
};

RCPP_MODULE(yada){
    using namespace Rcpp ;
    class_<World>( "World" )
    .constructor<SEXP>()
    .method( "get", &World::get     , "get a list element" )
    .method( "put", &World::put     , "put a list element" )
    ;
}


## in R
mytest <- function(nr=2, nc=3) {
  inmat = matrix(1:(nr*nc), nrow=nr);
  colnames(inmat) = letters[1:nc];
  rownames(inmat) = letters[1:nr];
  aa <- new(World, inmat)
  ret1 <- aa$get("a")
  aa$put("a", 17L)
  ret2 <- aa$get("a")
  list(ret1, ret2)
}


-- 
A man, a plan, a cat, a ham, a yak, a yam, a hat, a canal – Panama!


More information about the Rcpp-devel mailing list