Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does R handle object in function call?

Tags:

object

r

I have background of Java and Python and I'm learning R recently.

Today I found that R seems to handle objects quite differently from Java and Python.

For example, the following code:

x <- c(1:10)
print(x)
sapply(1:10,function(i){
            x[i] = 4
        })
print(x)

The code gives the following result:

[1]  1  2  3  4  5  6  7  8  9 10
[1]  1  2  3  4  5  6  7  8  9 10

But I expect the second line of output to be all '4' since I modified the vector in the sapply function.

So does this mean that R make copies of objects in function call instead of reference to the objects?

like image 574
Derrick Zhang Avatar asked Sep 24 '11 05:09

Derrick Zhang


People also ask

What is the use of do call in R?

The do.call The do.call R function executes a function by its name and a list of corresponding arguments. The call The call R function creates objects of the class “call”.

What is a function in R?

A function in R is an object that implements its task and returns control to the interpreter, and whatever result may be stored in other objects. A function is a set of statements constructed together to perform a particular task, and the R language has a large number of inbuilt functions, and the user can create their own functions.

What is an object in R?

These objects can be almost anything, from a single number or character string (like a word) to highly complex structures like the output of a plot, a summary of your statistical analysis or a set of R commands that perform a specific task. Understanding how you create objects and assign values to objects is key to understanding R.

How do I call objectobjects from a list?

Objects of mode "list" can be coerced to mode "call" . The first element of the list becomes the function part of the call, so should be a function or the name of one (as a symbol; a quoted string will not do). If you think of using as.call (<string>), consider using str2lang (*) which is an efficient version of parse (text=*) .


2 Answers

x is defined in the global environment, not in your function.

If you try to modify a non-local object such as x in a function then R makes a copy of the object and modifies the copy so each time you run your anonymous function a copy of x is made and its ith component is set to 4. When the function exits the copy that was made disappears forever. The original x is not modified.

If we were to write x[i] <<- i or if we were to write x[i] <- 4; assign("x", x, .GlobalEnv) then R would write it back. Another way to write it back would be to set e, say, to the environment that x is stored in and do this:

e <- environment()
sapply(1:10, function(i) e$x[i] <- 4)

or possibly this:

sapply(1:10, function(i, e) e$x[i] <- 4, e = environment())

Normally one does not write such code in R. Rather one produces the result as the output of the function like this:

x <- sapply(1:10, function(i) 4)

(Actually in this case one could write x[] <- 4.)

ADDED:

Using the proto package one could do this where method f sets the ith component of the x property to 4.

library(proto)

p <- proto(x = 1:10, f = function(., i) .$x[i] <- 4)

for(i in seq_along(p$x)) p$f(i)
p$x

ADDED:

Added above another option in which we explicitly pass the environment that x is stored in.

like image 200
G. Grothendieck Avatar answered Sep 18 '22 15:09

G. Grothendieck


Yes, you're right. Check the R Language Definition: 4.3.3 Argument Evaluation

AFAIK, R doesn't really copy the data until you're trying to modify it, thus following the Copy-on-write semantics.

like image 25
Anatoliy Avatar answered Sep 17 '22 15:09

Anatoliy