a and b are the same object: 

> a <- seq(1, 0.1, -0.1)
> b <- a
> pryr::address( a )
[1] "0x7f9504534948"
> pryr::address( b )
[1] "0x7f9504534948"

So clone is what you need here. 

Implementing copy on write for that kind of example is possible, but would 
require a lot of additional code, i.e. the iterator would need to handle the 
write operation. 

An undesirable side effect of this is that such iterators would be quite less 
performant, right now Rcpp is close to the metal and uses direct pointers as 
iterators when it makes sense. A price that everyone would have to pay. no go. 

Instead, the responsibility is given to the user to clone explicitly when 
changes will be made to the underlying object. 

Romain 


> Le 22 oct. 2014 à 04:13, Chenliang Xu <luckyr...@gmail.com> a écrit :
> 
> Hi Dirk,
> 
> Thanks for your quick answer. I don't think Rcpp::clone is what I was looking 
> for. I know `stl_sort_inplace(a)` modify the value of `a`, but it surprise me 
> to see it modify `b`. And it may modify some other variables c, d, e, f..., 
> and it's hard to know which variables point to the same place.
> 
> On Tue, Oct 21, 2014 at 8:31 PM, Dirk Eddelbuettel <e...@debian.org 
> <mailto:e...@debian.org>> wrote:
> 
> On 21 October 2014 at 20:22, Chenliang Xu wrote:
> | Hello,
> |
> | With the following inplace sorting example, I understand the value of `a` is
> | sorted inplace, but it's strange to see the value of `b` is also modified. 
> This
> | can cause some hard to detect bug, since the cpp function may modify a 
> variable
> | defined in other scope.
> 
> Very well known issue -- maybe do a search for 'Rcpp::clone' ...
> 
> In a nutshell, SEXP objects are passed by a __pointer__ and changes do
> therefore persist.  If you want distinct copies, use Rcpp::clone().
> 
> Dirk
> 
> | It seems that rcpp doesn't respect the named field, which is adopted by R to
> | implement copy-on-modify. I don's see an easy fix on C++ side, since the 
> called
> | cpp function has no information about variable binding in R. A possible fix 
> is
> | adding a function `inplace` to R, which ensure the returned variable has 
> named
> | filed = 0 so is safe to modify inplace. Then, we have to call the function 
> as
> | `stl_sort_inplace(inplace(a))`, which seems odd but is also informative. It
> | shows clearly that we are breaking the pass-by-value rule in R.
> |
> | ```cpp
> | #include <Rcpp.h>
> | using namespace Rcpp;
> |
> | // [[Rcpp::export]]
> | void stl_sort_inplace(NumericVector x) {
> |     std::sort(x.begin(), x.end());
> | }
> |
> | ```
> |
> | ```r
> | a <- seq(1, 0.1, -0.1)
> | b <- a
> | #  [1] 1.0 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1
> |
> | stl_sort_inplace(a)
> |
> | a
> | #  [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> |
> | b
> | #  [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> |
> | a <- seq(1, 0.1, -0.1)
> | pure_function <- function (x) {
> |   y <- x
> |   stl_sort_inplace(y)
> |   print(y)
> | }
> | pure_function(a)
> | a
> | #  [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> |
> | ```
> |
> | _______________________________________________
> | Rcpp-devel mailing list
> | Rcpp-devel@lists.r-forge.r-project.org 
> <mailto:Rcpp-devel@lists.r-forge.r-project.org>
> | https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel 
> <https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel>
> 
> --
> http://dirk.eddelbuettel.com <http://dirk.eddelbuettel.com/> | @eddelbuettel 
> | e...@debian.org <mailto:e...@debian.org>
> 
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel@lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to