## Call by reference in R

Sometimes it is convenient to use “call by reference evaluation” inside an R function. For example, if you want to have multiple return value for your function, then either you return a list of return value and split them afterward or you can return the value via the argument.

For some reasons(I would like to know too), R do not support call by reference. The first reason come up in my mind is safety, if the function can do call by reference, it is more difficult to trace the code and debug(you have to find out which function change the value of your variables by examining the details of your function). In fact, R do “call by reference” when the value of the argument is not changed. They will make a copy of the argument only when the value is changed. So we can expect there’s no efficiency gain (at least not a significant one) even we can do call by reference.

Anyway, it is always good to know how to have a “pseudo call by reference” in R (you can choose (not) to use it for whatever reason). The trick to implement call by reference is to make use of the eval.parent function in R. You can add a code to replace the argument value in the parent environment so that the function looks like implementing the call by reference evaluation strategy. Here are some examples of how to do it:

set<-function(x,value){ eval.parent(substitute(x<-value)) } valX <- 51 set(valX ,10) valX >[1] 10

addOne_1<-function(x,value){ eval.parent(substitute(x<-x+1)) } valX <- 51 addOne_1(valX) valX >[1] 52

Note that you could not change the value of x inside the function. If you change the value of x, a new object will be created. The substitute function will replace x with the new value and hence this method wont work. For example

addOne_2<-function(x,value){ x<-x+1 eval.parent(substitute(x<-x)) } valX <- 51 addOne_2(valX) >Error in 52 <- 52 : invalid (do_set) left-hand side to assignment

If you want to change the value of x inside the function, you have to copy x to a new object and use new object as x. At the end of the function, you can replace the value of x with the new object at the parent environment.

addOne_3<-function(x,value){ xx<-x xx<-xx+1 eval.parent(substitute(x<-xx)) } valX <- 51 addOne_3(valX) valX >[1] 52

Another way to do call by reference more formally is using the R.oo packages.

Another way to implement

## A shortcut function for install.packages() and library()

I enjoy trying difference kind of R packages. Since I have more than 1 computers (1 at home, 1 at office and a laptop)

it is troublesome to check whether I have installed some new packages for each computer. Therefore i wrote a function to load and install packages at once. If the package does not exist, then the it will be downloaded from CRAN and be loaded it.

packages<-function(x, repos="http://cran.r-project.org", ...){ x <- deparse(substitute(x)) if (!require(x,character.only=TRUE)){ install.packages(pkgs=x, repos=repos, ...) require(x,character.only=TRUE) } } packages(Hmisc)

Thanks richierocks for the suggestion of using deparse(substitute(x)) in the code.

richierocks’s

## A quick way to do row repeat and col repeat (rep.row, rep.col)

Today I worked on a simulation program which require me to create a matrix by repeating the vector n times (both by row and by col).

Even the task is extremely simple and only take 1 line to finish(10sec), I have to think about should the argument in rep be each or times and should the argument in matrix is nrow or ncol. It distracted me from the original task i am working on.

Just now, I wrote a function rep.row and rep.col to do what I really want to do. Next time, i don’t have to worry about how to use the matrix and rep command to repeat an vector to form a matrix!

Code

rep.row<-function(x,n){ matrix(rep(x,each=n),nrow=n) } rep.col<-function(x,n){ matrix(rep(x,each=n), ncol=n, byrow=TRUE) }

x is the vector to be repeated and n is the number of replication. Example:

> rep.row(1:3,5) [,1] [,2] [,3] [1,] 1 2 3 [2,] 1 2 3 [3,] 1 2 3 [4,] 1 2 3 [5,] 1 2 3 > rep.col(1:3,5) [,1] [,2] [,3] [,4] [,5] [1,] 1 1 2 2 3 [2,] 1 1 2 3 3 [3,] 1 2 2 3 3

I am sure it should appear in some packages, but it would be faster for me to write it out than find it out!