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:
REALSXP
for numeric vectors,INTSXP
for integer vectors,VECSXP
for listsWe’ll start with a simple example: an Rcpp function that takes a list, loops through it, and:
A quick test:
[[1]] [1] 2 3 4 5 6 [[2]] [1] 2 4 6 8 10
Some notes on the above:
TYPEOF
, and do something
for the case of numeric vectors (REALSXP
), and integer vectors (INTSXP
),Rcpp::as
to wrap the R object with the appropriate container,default:
switch just to do nothing or fall through,
or handle other SEXP
s as needed as well.We also check that we fail gracefully when we encounter a non-accepted SEXP
:
<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
is a VECSXP
, then we just call our recursive function on that element itself!
A test case:
$x [1] 2 3 4 5 6 $y [1] 2 4 6 8 10 $z $z$zx [1] 11 $z$zy [1] 40
Note that all we had to do was add a VECSXP
case in our switch
statement.
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.
tags: basics recursion function
Tweet