[Rcpp-devel] Unintentional modification of vector in place?

Dirk Eddelbuettel edd at debian.org
Mon Mar 20 18:44:30 CET 2017


Hi Evan,

You mostly got all of this right; the topic has also been discussed a number
of times before here, on SO and in other places.

On 20 March 2017 at 11:19, Evan Cortens wrote:
| Hi folks,
| 
| First, thanks for an amazing package! This is my first post to the Rcpp
| listserv, so please forgive me if I'm missing something obvious.
| 
| I've just noticed what, to me at least, is rather unexpected behaviour, as
| follows:
| 
| # Here's the Rcpp function
| library(Rcpp)
| 
| cppFunction('IntegerVector test_int_vec(IntegerVector x) {
|   for ( R_xlen_t i = 0; i < x.size(); i++ )
|     x[i] = x[i] * 2;
|   return x;
| }')
| 
| # This works as expected
| > a <- c(1, 2, 3, 4, 5)
| > a
| [1] 1 2 3 4 5
| > test_int_vec(a)
| [1]  2  4  6  8 10
| > a
| [1] 1 2 3 4 5
| 
| # But this doesn't
| > b <- c(1L, 2L, 3L, 4L, 5L)
| > b
| [1] 1 2 3 4 5
| > test_int_vec(b)
| [1]  2  4  6  8 10
| > b
| [1]  2  4  6  8 10
| 
| 
| You'll see that in the first example, in which I pass a numeric vector, the
| function acts as I'd expect it, namely, it returns the result of the
| calculation, leaving the original vector unmodified. However, in the second
| example, when I pass it an integer vector, it modifies the vector in place, and
| the original vector is changed.

Proxy objects.

In case two an integer vector is passed as such and modified. In case one the
integer vector _has to be copied first_ to a double vec, hence no in place mod.

| I can only imagine this has something to do with implicit coercion: when the
| reals are coerced to integers in the first example, the vector must be cloned,
| whereas in the second example, in which no coercion is necessary, it's a
| pointer to the original data. Another thing that leads me to believe this is
| that the same thing happens in reverse if you change the return/variable type
| of the function to NumericVector--reals end up being modified in place and
| integers aren't.
| 
| In my mind, one of the following things should happen:
| 1) In both situations, the vector is modified in place.

It does _when the object passed is of the same type as the object in the
signature_.  It it will happen to a numeric vector when you use Rcpp::NumericVector.

| 2) In both situations, the vector is copied--probably this isn't right, as it
| makes it impossible to modify in place.

Also performance loss that will get worse as the date gets larger.

| 3) Allow modification in place, but throw an error if the wrong type is passed.

You may have to write a new compiler ... as casting from int to double is
pretty standard.

Dirk
| 
| Is this a bug? Am I just misunderstanding? Any help would be appreciated!
| 
| Thanks in advance and all best,
| 
| Evan
| 
| =====
| 
| > sessionInfo()
| R version 3.3.2 (2016-10-31)
| Platform: x86_64-w64-mingw32/x64 (64-bit)
| Running under: Windows 7 x64 (build 7601) Service Pack 1
| 
| locale:
| [1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252
|    LC_MONETARY=English_United States.1252 LC_NUMERIC=C                        
|  
| [5] LC_TIME=English_United States.1252    
| 
| attached base packages:
| [1] stats     graphics  grDevices utils     datasets  methods   base     
| 
| other attached packages:
| [1] Rcpp_0.12.10
| 
| loaded via a namespace (and not attached):
| [1] tools_3.3.2     withr_1.0.2     memoise_1.0.0   digest_0.6.12  
| devtools_1.12.0
| 
| 
| --
| Evan Cortens, PhD
| Institutional Analyst - Office of Institutional Analysis
| Mount Royal University
| 403-440-6529
| _______________________________________________
| 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

-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list