[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