[Rcpp-devel] type information about elements in Rcpp::List

Dirk Eddelbuettel edd at debian.org
Wed May 9 22:55:42 CEST 2012


On 9 May 2012 at 16:38, Bob Carpenter wrote:
| Thanks again, Dirk, for being so responsive to
| our newbie queries.  There's some more inline below.
| 
| On 5/8/12 11:34 PM, Dirk Eddelbuettel wrote:
|  >
|  > On 8 May 2012 at 23:17, Jiqiang Guo wrote:
|  > | Suppose I have a function in CPP as
|  > |
|  > | void cppfun(Rcpp::List lst) {
|  > |     ......
|  > | }
|  > |
|  > | Then I would like to call this cppfun in R code as say
|  > | cppfun(list(a=a, b=b, c=c, ...)), in which
|  >
|  > (Well you need a SEXP somefun(SEXP ...) interface from R)
| 
| We (I'm working with Jiqiang) were hoping to
| let Rcpp do the heavy wrapping here following
| the std::vector example in the Rcpp modules doc (last
| full example).
| 
|  > | a, b, c could be of different types and their type might be 
| different as this
|  > | function gets called another time.  So I would like to know the 
| type of a, b,
|  > | c in the CPP code.  Could someone help me out or point to me some other
|  > | approaches?  Thanks.
|  >
|  > It's a good question. I have at time thought about that a little, but 
| have no
|  > immediate solution for you.
|  >
|  > One could possible use something C++-ish via traits.
| 
| We are using traits/policies all over our own code,
| but this isn't a compile-time type/behavioral config issue.  The
| types someone passes us in a call that takes a list
| could be anything, and we need to check they're compatible
| with what we're expecting and handle the error if they're
| not.
| 
|  > One could also use C level macros from the R API which simply test 
| for types
|  > as after all each element of a List must be a SEXP, so we use the 
| SEXP-style
|  > macros.
| 
| This could work.  We just don't know what's in an
| SEXP or how to get the SEXP from the Rcpp::List entries.

See below for a stylized (working) example.
 
| What we (I'm working with Jiqiang) need is to be able to
| 
|    1.  access the value of an Rcpp list entry by name.

Name or position work, yes.  

But if you know the name, don't you know the type too?

|    2.  recover the basic type, integer or floating point

Integer always casts up to float so you get just use NumericVector if ...

|    3.  recover the dimensions

... all you want is the length.

|    4.  recover the values as a vector

My stylized example does that, allbeit for matrices.
 
| Presumably that's available somewhere in the Rcpp::List
| if you can use it to communicate back and forth
| losslessly with R.

Sort of. Rcpp::List allows for mixed types, just as in R. In C/C++, these are
SEXP.  And SEXP can be converted via Rcpp::as<> or implicitly because that is
what Rcpp does anyway.
 
|  > In the end I always went with more explicit code design: only use a 
| List for
|  > transfer to / from R, and otherwise use explicit C++ types.
| 
| I completely agree with Dirk's last point -- we only
| want to use Rcpp as transport to/from R.
| 
| Is there a place to find the API doc somewhere,
| like what methods are available on an Rcpp::List?

There are our writeups, ie the vignettes.  

But there is so much code that it is hard to document all.  There is the
doxygen generated documentation too.


| Otherwise, I can just look at the code.  I'm about to
| try to look through the source now, so maybe I'll be
| able to answer our own question.
| 
| - Bob

Here is a simple example:


R> 
R> suppressMessages(library(inline))
R> 
R> src <- '
+   Rcpp::List lst(lstSexp);
+ 
+   int n = lst.length();
+   Rcpp::IntegerMatrix dims(n, 2);
+ 
+   for (int i=0; i<n; i++) {
+      SEXP s = lst[i];            // could also go by name
+      if (Rf_isInteger(s)) {      // isInteger() from R API
+         Rcpp::IntegerMatrix m(s);
+         dims(i,0) = m.nrow();
+         dims(i,1) = m.ncol();
+      } else if (Rf_isNumeric(s)) {  // idem
+         Rcpp::NumericMatrix m(s);
+         dims(i,0) = m.nrow();
+         dims(i,1) = m.ncol();
+      } else if (Rf_isString(s)) {  // idem
+         Rcpp::CharacterMatrix m(s);
+         dims(i,0) = m.nrow();
+         dims(i,1) = m.ncol();
+      } else {
+         dims(i,0) = R_NaInt;
+         dims(i,1) = R_NaInt;
+      }
+   }
+   return dims;
+ '
R> 
R> fun <- cxxfunction(signature(lstSexp="list"), # types are checked, 'list' just for info
+                    body=src,
+                    plugin="Rcpp")
R> 
R> fun(list(a=matrix(1:9,3,3), b=matrix(1L:4L,2,2), c=NULL, d=new.env(), e=rnorm))
     [,1] [,2]
[1,]    3    3
[2,]    2    2
[3,]   NA   NA
[4,]   NA   NA
[5,]   NA   NA
R> 


Notice how we pass two different matrices, a NULL, an environment and a
function just for kicks.

Hope this helps,  Dirk

| 
| 
| 
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

-- 
R/Finance 2012 Conference on May 11 and 12, 2012 at UIC in Chicago, IL
See agenda, registration details and more at http://www.RinFinance.com


More information about the Rcpp-devel mailing list