tplate@blackmesacapital.com
2005-Jun-09 19:13 UTC
[Rd] single assignment affecting multiple sub-structures (PR#7924)
I'm trying to create a language structure that is a call to a function
with a number of arguments that is only known at run time. I do this by
using repeated indices to expand out a call with a single argument.
However, when I change one of the arguments, all are changed.
I don't see the same behavior when I initially create a call with
multiple arguments.
Even more strangely, calling identical(call1, call2) before any attempts
to modify the structures changes the subsequent behavior to be correct.
[If there are better methods to create and modify calls, please let me
know!]
> # Example of commands that give incorrect results
> call1 <- Quote(f(arg[[1]], arg[[1]], arg[[1]]))
> call2 <- Quote(f(arg[[1]]))[c(1,2,2,2)]
> call1
f(arg[[1]], arg[[1]], arg[[1]])
> call2
f(arg[[1]], arg[[1]], arg[[1]])
> call1[[3]][[3]] <- 2
> call2[[3]][[3]] <- 2
> call1
f(arg[[1]], arg[[2]], arg[[1]])
> # note that all the arguments of call2 have changed!
> call2
f(arg[[2]], arg[[2]], arg[[2]])
> identical(call1, call2)
[1] FALSE
>
> # if we do 'identical(call1, call2)' directly
> # after creation, then everything behaves correctly !??
> call1 <- Quote(f(arg[[1]], arg[[1]], arg[[1]]))
> call2 <- Quote(f(arg[[1]]))[c(1,2,2,2)]
> identical(call1, call2)
[1] TRUE
> call1
f(arg[[1]], arg[[1]], arg[[1]])
> call2
f(arg[[1]], arg[[1]], arg[[1]])
> call1[[3]][[3]] <- 2
> call2[[3]][[3]] <- 2
> call1
f(arg[[1]], arg[[2]], arg[[1]])
> call2
f(arg[[1]], arg[[2]], arg[[1]])
> identical(call1, call2)
[1] TRUE
>
> # The same thing happens when the call is created using 'call()'
> call3 <- call("f", call("[[",
as.name("arg"), 1))[c(1,2,2,2)]
> call3
f(arg[[1]], arg[[1]], arg[[1]])
> call3[[3]][[3]] <- 2
> call3
f(arg[[2]], arg[[2]], arg[[2]])
>
> version
_
platform i386-pc-mingw32
arch i386
os mingw32
system i386, mingw32
status
major 2
minor 1.0
year 2005
month 04
day 18
language R
>
I also see the same behavior in the development release of R:
> version
_
platform i386-pc-mingw32
arch i386
os mingw32
system i386, mingw32
status Under development (unstable)
major 2
minor 2.0
year 2005
month 06
day 07
svn rev 34588
language R
>
-- Tony Plate
Tony Plate
2005-Jun-11 13:18 UTC
[Rd] single assignment affecting multiple sub-structures (PR#7924)
Yes, actually, I have had code using do.call() that returns the result I want working for years. However, I've been trying to reduce the memory usage of my code, and I discovered that in S-PLUS, do.call() appears to make a extra copy of its arguments. When the arguments are very large, this can be important. I found that by constructing a call like the one below, and eval()ing it, S-PLUS would not make unnecessary copies of the arguments. However, when I tried the same code in R, I found the bug that I described below. -- Tony Plate Douglas Bates wrote:> I hesitate to make such as simplistic suggestion but have you > considered using do.call to generate the call? > > On 6/9/05, tplate at blackmesacapital.com <tplate at blackmesacapital.com> wrote: > >>I'm trying to create a language structure that is a call to a function >>with a number of arguments that is only known at run time. I do this by >>using repeated indices to expand out a call with a single argument. >>However, when I change one of the arguments, all are changed. >> >>I don't see the same behavior when I initially create a call with >>multiple arguments. >> >>Even more strangely, calling identical(call1, call2) before any attempts >>to modify the structures changes the subsequent behavior to be correct. >> >>[If there are better methods to create and modify calls, please let me >>know!] >> >> > # Example of commands that give incorrect results >> > call1 <- Quote(f(arg[[1]], arg[[1]], arg[[1]])) >> > call2 <- Quote(f(arg[[1]]))[c(1,2,2,2)] >> > call1 >>f(arg[[1]], arg[[1]], arg[[1]]) >> > call2 >>f(arg[[1]], arg[[1]], arg[[1]]) >> > call1[[3]][[3]] <- 2 >> > call2[[3]][[3]] <- 2 >> > call1 >>f(arg[[1]], arg[[2]], arg[[1]]) >> > # note that all the arguments of call2 have changed! >> > call2 >>f(arg[[2]], arg[[2]], arg[[2]]) >> > identical(call1, call2) >>[1] FALSE >> > >> > # if we do 'identical(call1, call2)' directly >> > # after creation, then everything behaves correctly !?? >> > call1 <- Quote(f(arg[[1]], arg[[1]], arg[[1]])) >> > call2 <- Quote(f(arg[[1]]))[c(1,2,2,2)] >> > identical(call1, call2) >>[1] TRUE >> > call1 >>f(arg[[1]], arg[[1]], arg[[1]]) >> > call2 >>f(arg[[1]], arg[[1]], arg[[1]]) >> > call1[[3]][[3]] <- 2 >> > call2[[3]][[3]] <- 2 >> > call1 >>f(arg[[1]], arg[[2]], arg[[1]]) >> > call2 >>f(arg[[1]], arg[[2]], arg[[1]]) >> > identical(call1, call2) >>[1] TRUE >> > >> > # The same thing happens when the call is created using 'call()' >> > call3 <- call("f", call("[[", as.name("arg"), 1))[c(1,2,2,2)] >> > call3 >>f(arg[[1]], arg[[1]], arg[[1]]) >> > call3[[3]][[3]] <- 2 >> > call3 >>f(arg[[2]], arg[[2]], arg[[2]]) >> > >> > version >> _ >>platform i386-pc-mingw32 >>arch i386 >>os mingw32 >>system i386, mingw32 >>status >>major 2 >>minor 1.0 >>year 2005 >>month 04 >>day 18 >>language R >> > >> >> >>I also see the same behavior in the development release of R: >> > version >> _ >>platform i386-pc-mingw32 >>arch i386 >>os mingw32 >>system i386, mingw32 >>status Under development (unstable) >>major 2 >>minor 2.0 >>year 2005 >>month 06 >>day 07 >>svn rev 34588 >>language R >> > >> >>-- Tony Plate >> >>______________________________________________ >>R-devel at stat.math.ethz.ch mailing list >>https://stat.ethz.ch/mailman/listinfo/r-devel >> > >