> -----Original Message----- > From: r-help-boun...@r-project.org > [mailto:r-help-boun...@r-project.org] On Behalf Of Stephen Tucker > Sent: Tuesday, February 16, 2010 5:32 PM > To: r-help@r-project.org > Subject: [R] side-effects in functions that replace object > values andattributes > > Hello list, > > I encountered some surprising behavior in R and wanted to > check to see if I was imagining things. Previously, I thought > that replacement/setter operators in prefix notation (e.g., > `[<-`(x,1,y) rather than x[1] <- y) did not produce side > effects (i.e., left 'x' unchanged), but just realized that > this is not the case anymore (or has it always been this way? > - I don't have access to old R distributions at the moment, > but using R 2.10.1 on Ubuntu and OS X)? I went through the > NEWS file but did not see a change documented if there was > one, but just going by my recollection... > > In any case, my understanding was that when modifying a value > or attribute of an object, R reassigned the modified object > to the original symbol. For instance, the help file for > `name<-`() says that > > > names(z)[3] <- "c2" > > is evaluated as > > > z <- "names<-"(z, "[<-"(names(z), 3, "c2")) > > But the final (re)assignment (`<-`) seems redundant as > > > invisible("names<-"(z, "[<-"(names(z), 3, "c2"))) > > does the same thing. > > In this case, I wonder if there is a preferred way to use the > replacement/setter operators in prefix notation without > producing such side effects
I would never recommend using replacement operators this way. In part this is because S+ doesn't like it: S+> x<-1:10 S+> `[<-`(x, 1, value=66.6) [1] 66.6 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 Warning messages: looks like the internal reference count was not updated in: x[1] <- 66.6 S+> x [1] 1 2 3 4 5 6 7 8 9 10 in part because it is ugly, but mostly it is because forcing the program to accept such usage closes off, or at least restricts, an avenue for saving memory when doing replacement operations. If you have a replacement function that you are tempted to use in this way, I recommend that you write a wrapper function for it. E.g., instead of using namedX <- `names<-`(x, value=as.character(x)) write setNames <- function(x, names) { names(x) <- names x } and use it as namesX <- setNames(x, as.character(x)) Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com > (replace() exists for `[<-`() and > `[[<-`(), but perhaps something more general). For instance, > if I did not desire the following modification in x: > > > x <- c("1","2") > > y <- `names<-`(x,c("a","b")) > > y > a b > "1" "2" > > x > a b > "1" "2" > > > > I might take advantage of R's lazy evaluation and use create > a copy in the local function environment and allow that copy > to be modified: > > > x <- c("1","2") > > y <- `names<-`(`<-`(x,x),c("a","b")) > > y > a b > "1" "2" > > x > [1] "1" "2" > > The interesting thing is that `mode<-`(), while also a > "setter" function in that it sets an object attribute, does > not behave as `names<-`(): > > > x <- c("1","2") > > y <- `mode<-`(x,"integer") > > y > [1] 1 2 > > x > [1] "1" "2" > > mode(x) > [1] "character" > > So another question that naturally arises is whether there a > general rule by which we can predict the behavior of these > types of operators (whether they produce side effects or not)? > > Thanks, > > Stephen > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.