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?
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”.
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.
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.
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=*) .
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With