R: Pass by reference

Can you pass the link "R"? for example in the following code:

setClass("MyClass", representation( name="character" )) instance1 <-new("MyClass",name="Hello1") instance2 <-new("MyClass",name="Hello2") array = c(instance1,instance2) instance1 array instance1@name="World!" instance1 array 

output

 > instance1 An object of class "MyClass" Slot "name": [1] "World!" > array [[1]] An object of class "MyClass" Slot "name": [1] "Hello1" [[2]] An object of class "MyClass" Slot "name": [1] "Hello2" 

but I'm sorry it was

 > instance1 An object of class "MyClass" Slot "name": [1] "World!" > array [[1]] An object of class "MyClass" Slot "name": [1] "World!" [[2]] An object of class "MyClass" Slot "name": [1] "Hello2" 

Is it possible?

thank

Pierre

+42
pass-by-reference oop r argument-passing
Apr 08 '10 at 20:23
source share
9 answers

No.

Objects in assignment statements are immutable. R will copy an object not only a link.

 > v = matrix(1:12, nrow=4) > v [,1] [,2] [,3] [1,] 1 5 9 [2,] 2 6 10 [3,] 3 7 11 [4,] 4 8 12 > v1 = v > v1[,1] # fetch the first column [1] 1 2 3 4 

(disclaimer: the above statement is valid for R-primitives, for example vectors, matrices), as well as for functions; I can’t say for sure whether this is true for all R objects - only most of them, as well as the vast majority of the most commonly used ones.)

If you don’t like this behavior, you can opt out of it using the R. package. For example, there is an R package called R.oo that allows you to mimic the behavior of a step-by-step link; R.oo is available on CRAN .

+46
Apr 08 2018-10-10T00:
source share

Note that if you want to use pass-by-reference simply to avoid the consequences of copying an object that has not been modified (as is often found in other languages ​​with permalinks), R does this automatically:

 n <- 10^7 bigdf <- data.frame( x=runif(n), y=rnorm(n), z=rt(n,5) ) myfunc <- function(dat) invisible(with( dat, x^2+mean(y)+sqrt(exp(z)) )) myfunc2 <- function(dat) { x <- with( dat, x^2+mean(y)+sqrt(exp(z)) ) invisible(x) } myfunc3 <- function(dat) { dat[1,1] <- 0 invisible( with( dat, x^2+mean(y)+sqrt(exp(z)) ) ) } tracemem(bigdf) > myfunc(bigdf) > # nothing copied > myfunc2(bigdf) > # nothing copied! > myfunc3(bigdf) tracemem[0x6e430228 -> 0x6b75fca0]: myfunc3 tracemem[0x6b75fca0 -> 0x6e4306f0]: [<-.data.frame [<- myfunc3 tracemem[0x6e4306f0 -> 0x6e4304f8]: [<-.data.frame [<- myfunc3 > > library(microbenchmark) > microbenchmark(myfunc(bigdf), myfunc2(bigdf), myfunc3(bigdf), times=5) Unit: milliseconds expr min lq median uq max 1 myfunc2(bigdf) 617.8176 641.7673 644.3764 683.6099 698.1078 2 myfunc3(bigdf) 1052.1128 1134.0822 1196.2832 1202.5492 1206.5925 3 myfunc(bigdf) 598.9407 622.9457 627.9598 642.2727 654.8786 
+34
Aug 01 '12 at 11:27
source share

Passing by reference is possible for environment s. You can try to use them: basically, when you create an object, you will also need to create an environment slot. But I think this is cumbersome. See Pointers and Link Followers in R and Follow the link for S4.

+15
Apr 08 2018-10-18T00:
source share

As mentioned earlier, this can be done using objects of the environment class. There is a formal approach based on the use of environment s. It is called Reference Classes and makes things very easy for you. Check out ?setRefClass on the main help page. It also describes how to use formal methods using reference classes.

Example

 setRefClass("MyClass", fields=list( name="character" ) ) instance1 <- new("MyClass",name="Hello1") instance2 <- new("MyClass",name="Hello2") array = c(instance1,instance2) instance1$name <- "World!" 

Exit

 > instance1 Reference class object of class "MyClass" Field "name": [1] "World!" > array [[1]] Reference class object of class "MyClass" Field "name": [1] "World!" [[2]] Reference class object of class "MyClass" Field "name": [1] "Hello2" 
+13
Mar 12 2018-12-12T00:
source share

In fact, the R.oo package emulates pass-by-reference behavior using environments.

+4
Jan 05 2018-11-11T00:
source share

R now has a library that allows you to do OOP using links. See ReferenceClasses , which is part of the package of methods.

+4
Jan 31 2018-12-12T00:
source share

In addition to the other answers here that actually pass your object by reference ( environment objects and Reference Classes), if you are just interested in a call-link for syntactic convenience (i.e. you are not against your data copied inside), you can emulate this by assigning the final value back to an external variable when returning:

 byRef <- function(..., envir=parent.frame(), inherits=TRUE) { cl <- match.call(expand.dots = TRUE) cl[c(1, match(c("envir", "inherits"), names(cl), 0L))] <- NULL for (x in as.list(cl)) { s <- substitute(x) sx <- do.call(substitute, list(s), envir=envir) dx <- deparse(sx) expr <- substitute(assign(dx, s, envir=parent.frame(), inherits=inherits)) do.call(on.exit, list(expr, add=TRUE), envir=envir) } } 

Then we can declare the arguments "on call":

 f <- function(z1, z2, z3) { byRef(z1, z3) z1 <- z1 + 1 z2 <- z2 + 2 z3 <- z3 + 3 c(z1, z2, z3) } x1 <- 10 x2 <- 20 x3 <- 30 # Values inside: print(f(x1, x2, x3)) # [1] 11 22 33 # Values outside: print(c(x1, x2, x3)) # [1] 11 20 33 

Please note: if you access variables “by reference” by their external names ( x1 , x3 ) anywhere inside the function, you will receive their unchanged values ​​from the outside. In addition, this implementation simply treats variable names as arguments, so indexed arguments like f(x[1], ...) will not work (although you could probably implement this with a bit more complicated manipulation with expressions to get around the limited assign ).

+2
Feb 20 '14 at 7:06
source share

As others have argued, this is not possible for S4 classes. But R now provides the option of an R6 library called a link . See official documentation

+2
Nov 10 '15 at 1:20
source share

In addition to other suggestions, you can also write C / C ++ functions using your arguments by reference and working in place, and call them directly in R thanks to Rcpp (among other things). See, In particular, this answer .

0
Aug 23 '17 at 14:56 on
source share



All Articles