Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you pass-by-reference in R?

Can you pass by reference with "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 

the output is

> 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 wish 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 ?

like image 717
Pierre Avatar asked Apr 08 '10 20:04

Pierre


People also ask

Does R pass by reference or value?

R passes everything by reference until you modify it. R creates a copy when you modify the object. You should always keep all the Object modifications in same function.

Can you pass an object by reference?

A mutable object's value can be changed when it is passed to a method. An immutable object's value cannot be changed, even if it is passed a new value. “Passing by value” refers to passing a copy of the value. “Passing by reference” refers to passing the real reference of the variable in memory.

How do you pass by reference?

Pass by reference (also called pass by address) means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function so that a copy of the address of the actual parameter is made in memory, i.e. the caller and the callee use the same variable for the parameter.


2 Answers

No.

Objects in assignment statements are immutable. R will copy the object not just the reference.

> 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 

(proviso: the statement above is true for R primitives, e.g., vectors, matrices), and also for functions; I cannot say for certain whether it's true for all R objects--just most of them, as well as the vast majority of the ones most often used.)

If you don't like this behavior you can opt out of it with the help from an R Package. E.g., there is an R Package called R.oo that allows you to mimic pass-by-reference behavior; R.oo is available on CRAN.

like image 53
doug Avatar answered Sep 26 '22 21:09

doug


Note that if you hope to use pass-by-reference simply to avoid the performance implications of copying an object that isn't modified (as is common in other languages with constant references), 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 
like image 21
Ari B. Friedman Avatar answered Sep 22 '22 21:09

Ari B. Friedman