What is the difference between assign() and <<- in R?
The normal approach to writing functions in R (as I understand) is to avoid side-effects and return a value from a function.
contained <- function(x) {
x_squared <- x^2
return(x_squared)
}
In this case, the value computed from the input into the function is returned. But the variable x_squared
is not available.
But if you need to violate this basic functional programming tenet (and I'm not sure how serious R is about this issue) and return an object from a function, you have two choices.
escape <- function(x){
x_squared <<- x^2
assign("x_times_x", x*x, envir = .GlobalEnv)
}
Both objects x_squared
and x_times_x
are returned. Is one met开发者_JS百科hod preferable to the other and why so?
Thomas Lumley answers this in a superb post on r-help the other day. <<-
is about the enclosing environment so you can do thing like this (and again, I quote his post from April 22 in this thread):
make.accumulator<-function(){
a <- 0
function(x) {
a <<- a + x
a
}
}
> f<-make.accumulator()
> f(1)
[1] 1
> f(1)
[1] 2
> f(11)
[1] 13
> f(11)
[1] 24
This is a legitimate use of <<-
as "super-assignment" with lexical scope. And not simply to assign in the global environment. For that, Thomas has these choice words:
The Evil and Wrong use is to modify variables in the global environment.
Very good advice.
According to the manual page here,
The operators
<<-
and->>
cause a search to made through the environment for an existing definition of the variable being assigned.
I've never had to do this in practice, but to my mind, assign
wins a lot of points for specifying the environment exactly, without even having to think about R's scoping rules. The <<-
performs a search through environments and is therefore a little bit harder to interpret.
EDIT: In deference to @Dirk and @Hadley, it sounds like assign
is the appropriate way to actually assign to the global environment (when that's what you know you want), while <<-
is the appropriate way to "bump up" to a broader scope.
As pointed out by @John in his answer, assign lets you specify the environment specifically. A specific application would be in the following:
testfn <- function(x){
x_squared <- NULL
escape <- function(x){
x_squared <<- x^2
assign("x_times_x", x*x, envir = parent.frame(n = 1))
}
escape(x)
print(x_squared)
print(x_times_x)
}
where we use both <<-
and assign
. Notice that if you want to use <<-
to assign to the environment of the top level function, you need to declare/initialise the variable. However, with assign
you can use parent.frame(1)
to specify the encapsulating environment.
精彩评论