1

I am struggling with modifying elements of R environments in-place using Rcpp. More specifically, I would like to define variables pointing to elements of an R environment to ease working with public fields of an R6 class.

Consider the following Rcpp function:

double update_data1_cpp(Environment &self, double x) {
  self["data"] = x;
  return self["data"];
}

It takes a reference to the environment 'self' (e.g. an R6 class object) and updates the 'data' field with the value of 'x'. How can I define a shorthand 'data_' for self["data"] without copying and still being able to modify 'data' in the environment 'self'?

I did not find an answer to that in the Rcpp guide on working with R6 classes https://gallery.rcpp.org/articles/handling-R6-objects-in-rcpp/.

This does not work (does not modify data in the environment), I guess it copies the value of 'data' in 'self' to 'data_' and then only modifies 'data_':

double update_data2_cpp(Environment &self, double x) {
  double data_ = self["data"];
  data_ = x;
  return self["data"];
}

Trying to create a pointer to the address of self["data"] fails with 'taking address of temporary'

double update_data3_cpp(Environment &self, double x) {
  double *data_ = &(self["data"]);
  data_ = &x;
  return self["data"];
}

I guess my Cpp pointer-magic is not strong enough to get through this :) Any help appreciated!

markalex
  • 8,623
  • 2
  • 7
  • 32
jack
  • 73
  • 1
  • 7
  • 2
    hm, I think the confusion on my part comes from the distinction between SEXP ('r types' like NumericVector) which are already pointers and to the underlying R objects in memory and C++ base types like 'double'. By declaring data_ to be of type double, the SEXP was cast to double and hence copied. Modifying it then has no impact on self["data"]. Declaring data_ to be a NumiericVector (or size 1) however keeps it a SEXP and maintains the link. – jack Dec 11 '22 at 21:15
  • 1
    And that is pretty much the key issue. A `double` is just that: eight bytes. In order to get anything to and from R, we need an `SEXP` (or something containing it: a wrapper like `RObject` or a mapped type like `NumericVector) and to create one of those _you have to copy_. – Dirk Eddelbuettel Dec 13 '22 at 15:17

0 Answers0