Copying objects prior to .Call

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Copying objects prior to .Call

Taylor B. Arnold
R-devel,

I have noticed that making a copy of an object in R prior to using
.Call on the original object can
cause the C code to alter not only the object passed to it but also
the copy in R. A simple example
is:

> x <- 2
> y <- x
> .Call("addOne", x, DUP=TRUE) # Changing DUP does not alter output
NULL
> x
[1] 3
> y
[1] 3

And corresponding simple C code:

"test.c":
#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>

SEXP addOne(SEXP input) {
  REAL(input)[0] = REAL(input)[0] + 1;
  return R_NilValue;
}

I assume that this is simply a result of lazy loading in R, and well
documented. My question is, do
there exist functions to (1) force R to make a copy of an object
(force() does not work), and (2) to check
whether two objects are actually pointing to the same memory address.
For question 1, I have
found specific operations which force a copy of a given datatype, but
would prefer a more general
solution.

Thank you,

Taylor

> sessionInfo()
R version 2.14.1 (2011-12-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] tools_2.14.1


--
Taylor B. Arnold
Department of Statistics
Yale University
24 Hillhouse Avenue
New Haven, CT 06520

e-mail: [hidden email]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Copying objects prior to .Call

Simon Urbanek

On Jan 11, 2012, at 12:08 PM, Taylor Arnold wrote:

> R-devel,
>
> I have noticed that making a copy of an object in R prior to using
> .Call on the original object can
> cause the C code to alter not only the object passed to it but also
> the copy in R.

Please see the docs - .Call does *NOT* have a DUP argument - you are responsible for duplication at all times if you make modifications (e.g. using duplicate()).

Cheers,
Simon


> A simple example
> is:
>
>> x <- 2
>> y <- x
>> .Call("addOne", x, DUP=TRUE) # Changing DUP does not alter output
> NULL
>> x
> [1] 3
>> y
> [1] 3
>
> And corresponding simple C code:
>
> "test.c":
> #include <R.h>
> #include <Rinternals.h>
> #include <Rmath.h>
>
> SEXP addOne(SEXP input) {
>   REAL(input)[0] = REAL(input)[0] + 1;
>   return R_NilValue;
> }
>
> I assume that this is simply a result of lazy loading in R, and well
> documented. My question is, do
> there exist functions to (1) force R to make a copy of an object
> (force() does not work), and (2) to check
> whether two objects are actually pointing to the same memory address.
> For question 1, I have
> found specific operations which force a copy of a given datatype, but
> would prefer a more general
> solution.
>
> Thank you,
>
> Taylor
>
>> sessionInfo()
> R version 2.14.1 (2011-12-22)
> Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
>
> locale:
> [1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
>
> attached base packages:
> [1] stats     graphics  grDevices utils     datasets  methods   base
>
> loaded via a namespace (and not attached):
> [1] tools_2.14.1
>
>
> --
> Taylor B. Arnold
> Department of Statistics
> Yale University
> 24 Hillhouse Avenue
> New Haven, CT 06520
>
> e-mail: [hidden email]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Copying objects prior to .Call

Douglas Bates-2
On Wed, Jan 11, 2012 at 11:49 AM, Simon Urbanek
<[hidden email]> wrote:
>
> On Jan 11, 2012, at 12:08 PM, Taylor Arnold wrote:
>
>> R-devel,
>>
>> I have noticed that making a copy of an object in R prior to using
>> .Call on the original object can
>> cause the C code to alter not only the object passed to it but also
>> the copy in R.

> Please see the docs - .Call does *NOT* have a DUP argument - you are responsible for duplication at all times if you make modifications (e.g. using duplicate()).

Except that duplicate will create a new SEXPREC and the original
poster wanted to modify the SEXPREC passed through a pointer in .Call.

Purposely changing the value of arguments to .Call is a bad design,
Taylor.  R is a functional language and this breaks the functional
semantics. It is the sort of thing that you do only when you can't
think of a better approach.  It may, perhaps, be justified if the R
objects you are passing happen to be fields in a reference class (see
?setRefClass) but otherwise it is just opening yourself up to errors.
At the level of C/C++ all R objects passed as arguments to .Call
should be regarded as

const SEXP


>> A simple example
>> is:
>>
>>> x <- 2
>>> y <- x
>>> .Call("addOne", x, DUP=TRUE) # Changing DUP does not alter output
>> NULL
>>> x
>> [1] 3
>>> y
>> [1] 3
>>
>> And corresponding simple C code:
>>
>> "test.c":
>> #include <R.h>
>> #include <Rinternals.h>
>> #include <Rmath.h>
>>
>> SEXP addOne(SEXP input) {
>>   REAL(input)[0] = REAL(input)[0] + 1;
>>   return R_NilValue;
>> }
>>
>> I assume that this is simply a result of lazy loading in R, and well
>> documented. My question is, do
>> there exist functions to (1) force R to make a copy of an object
>> (force() does not work), and (2) to check
>> whether two objects are actually pointing to the same memory address.
>> For question 1, I have
>> found specific operations which force a copy of a given datatype, but
>> would prefer a more general
>> solution.
>>
>> Thank you,
>>
>> Taylor
>>
>>> sessionInfo()
>> R version 2.14.1 (2011-12-22)
>> Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
>>
>> locale:
>> [1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
>>
>> attached base packages:
>> [1] stats     graphics  grDevices utils     datasets  methods   base
>>
>> loaded via a namespace (and not attached):
>> [1] tools_2.14.1
>>
>>
>> --
>> Taylor B. Arnold
>> Department of Statistics
>> Yale University
>> 24 Hillhouse Avenue
>> New Haven, CT 06520
>>
>> e-mail: [hidden email]
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Copying objects prior to .Call

Uwe Ligges-3
In reply to this post by Simon Urbanek


On 11.01.2012 18:49, Simon Urbanek wrote:

>
> On Jan 11, 2012, at 12:08 PM, Taylor Arnold wrote:
>
>> R-devel,
>>
>> I have noticed that making a copy of an object in R prior to using
>> .Call on the original object can
>> cause the C code to alter not only the object passed to it but also
>> the copy in R.
>
> Please see the docs - .Call does *NOT* have a DUP argument - you are responsible for duplication at all times if you make modifications (e.g. using duplicate()).
>
> Cheers,
> Simon
>
>
>> A simple example
>> is:
>>
>>> x<- 2
>>> y<- x
>>> .Call("addOne", x, DUP=TRUE) # Changing DUP does not alter output
>> NULL
>>> x
>> [1] 3
>>> y
>> [1] 3
>>
>> And corresponding simple C code:
>>
>> "test.c":
>> #include<R.h>
>> #include<Rinternals.h>
>> #include<Rmath.h>
>>
>> SEXP addOne(SEXP input) {
>>    REAL(input)[0] = REAL(input)[0] + 1;
>>    return R_NilValue;
>> }
>>
>> I assume that this is simply a result of lazy loading

In addition to Simon: it is "lazy evalution" rather than lazy loading in
this case.

Uwe


>> in R, and well
>> documented. My question is, do
>> there exist functions to (1) force R to make a copy of an object
>> (force() does not work), and (2) to check
>> whether two objects are actually pointing to the same memory address.
>> For question 1, I have
>> found specific operations which force a copy of a given datatype, but
>> would prefer a more general
>> solution.
>>
>> Thank you,
>>
>> Taylor
>>
>>> sessionInfo()
>> R version 2.14.1 (2011-12-22)
>> Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
>>
>> locale:
>> [1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
>>
>> attached base packages:
>> [1] stats     graphics  grDevices utils     datasets  methods   base
>>
>> loaded via a namespace (and not attached):
>> [1] tools_2.14.1
>>
>>
>> --
>> Taylor B. Arnold
>> Department of Statistics
>> Yale University
>> 24 Hillhouse Avenue
>> New Haven, CT 06520
>>
>> e-mail: [hidden email]
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Copying objects prior to .Call

Simon Urbanek

On Jan 11, 2012, at 1:04 PM, Uwe Ligges wrote:

>
>
> On 11.01.2012 18:49, Simon Urbanek wrote:
>>
>> On Jan 11, 2012, at 12:08 PM, Taylor Arnold wrote:
>>
>>> R-devel,
>>>
>>> I have noticed that making a copy of an object in R prior to using
>>> .Call on the original object can
>>> cause the C code to alter not only the object passed to it but also
>>> the copy in R.
>>
>> Please see the docs - .Call does *NOT* have a DUP argument - you are responsible for duplication at all times if you make modifications (e.g. using duplicate()).
>>
>> Cheers,
>> Simon
>>
>>
>>> A simple example
>>> is:
>>>
>>>> x<- 2
>>>> y<- x
>>>> .Call("addOne", x, DUP=TRUE) # Changing DUP does not alter output
>>> NULL
>>>> x
>>> [1] 3
>>>> y
>>> [1] 3
>>>
>>> And corresponding simple C code:
>>>
>>> "test.c":
>>> #include<R.h>
>>> #include<Rinternals.h>
>>> #include<Rmath.h>
>>>
>>> SEXP addOne(SEXP input) {
>>>   REAL(input)[0] = REAL(input)[0] + 1;
>>>   return R_NilValue;
>>> }
>>>
>>> I assume that this is simply a result of lazy loading
>
> In addition to Simon: it is "lazy evalution" rather than lazy loading in this case.
>

It is actually neither. `x` gets evaluated, but the value is shared with `y` because R has no reason to create a copy of identical information until modified. That's why the .Call() code must create a copy if it wants to touch the value that it received. Note that .Call does *not* get `x` itself - it gets a value obtained from the binding of `x` so the only legal way to modify `x` is to assign a value to it. You can try to be more efficieint and check if a value has references to it and prevent copying if it doesn't (see NAMED), but if it does, you have to copy it.

Cheers,
Simon
 


> Uwe
>
>
>>> in R, and well
>>> documented. My question is, do
>>> there exist functions to (1) force R to make a copy of an object
>>> (force() does not work), and (2) to check
>>> whether two objects are actually pointing to the same memory address.
>>> For question 1, I have
>>> found specific operations which force a copy of a given datatype, but
>>> would prefer a more general
>>> solution.
>>>
>>> Thank you,
>>>
>>> Taylor
>>>
>>>> sessionInfo()
>>> R version 2.14.1 (2011-12-22)
>>> Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
>>>
>>> locale:
>>> [1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
>>>
>>> attached base packages:
>>> [1] stats     graphics  grDevices utils     datasets  methods   base
>>>
>>> loaded via a namespace (and not attached):
>>> [1] tools_2.14.1
>>>
>>>
>>> --
>>> Taylor B. Arnold
>>> Department of Statistics
>>> Yale University
>>> 24 Hillhouse Avenue
>>> New Haven, CT 06520
>>>
>>> e-mail: [hidden email]
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>>
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel