Kevin Ushey — written Apr 8, 2013 — source
We can leverage small parts of the R’s C API in order to infer the type of objects directly at the run-time of a function call, and use this information to dynamically wrap objects as needed. We’ll also present an example of recursing through a list.
To get a basic familiarity with the main functions exported from R API, I recommend reading Hadley’s guide to R’s C internals guide here first, as we will be using some of these functions for navigating native R SEXPs. (Reading it will also give you an appreciation for just how much work Rcpp does in insulating us from the ugliness of the R API.)
From the R API, we’ll be using the
TYPEOF macro, as well as referencing the
internal R types:
REALSXPfor numeric vectors,
INTSXPfor integer vectors,
We’ll start with a simple example: an Rcpp function that takes a list, loops through it, and:
A quick test:
[]  2 3 4 5 6 []  2 4 6 8 10
Some notes on the above:
TYPEOF, and do something for the case of numeric vectors (
REALSXP), and integer vectors (
Rcpp::asto wrap the R object with the appropriate container,
default:switch just to do nothing or fall through, or handle other
SEXPs as needed as well.
We also check that we fail gracefully when we encounter a non-accepted
<Rcpp::exception: incompatible SEXP encountered; only accepts lists with REALSXPs and INTSXPs>
However, this only operates on top-level objects within the list. What if your list contains other lists, and you want to recurse through those lists as well?
It’s actually quite simple: if the internal R type of the object encountered
VECSXP, then we just call our recursive function on that element itself!
A test case:
$x  2 3 4 5 6 $y  2 4 6 8 10 $z $z$zx  11 $z$zy  40
Note that all we had to do was add a
VECSXP case in our
If we see a list, we call the same
recurse function on that list, and then
re-assign the result of that recursive call. Neat!
Hence, by using
TYPEOF to query the internal R type of objects pre-wrap, we
can wrap objects as needed into an appropriate container, and then use Rcpp
/ C++ code as necessary to modify them.