The normal approach to writing functions in R (as I understand) is to avoid side-effects and return a value from a function.
用R编写函数的常规方法(如我所知)是避免副作用并从函数中返回值。
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.
在这种情况下,返回从函数的输入中计算的值。但是变量x_squared不可用。
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.
但是,如果您需要违背这个基本的函数编程原则(我不确定R对于这个问题有多严重),并从函数返回一个对象,那么您有两个选择。
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 method preferable to the other and why so?
返回对象x_squared和x_times_x。一种方法比另一种更可取吗?为什么?
3 个解决方案
#1
18
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):
托马斯·拉姆利(Thomas Lumley)在《r-help》(r-help)杂志上的一篇精彩文章中回答了这个问题。<<-是关于封闭环境的,所以你可以这样做(同样,我在这篇文章中引用了他4月22日的文章):
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:
这是<< <- as "super-assignment"在词法上的合理使用。而不仅仅是在全球环境中进行分配。为此,托马斯选择了以下字眼:
The Evil and Wrong use is to modify variables in the global environment.
恶意和错误的用法是修改全局环境中的变量。
Very good advice.
非常好的建议。
#2
2
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.
我从来没有在实践中这样做过,但是在我看来,为精确地指定环境而赋值可以赢得很多分数,甚至不需要考虑R的范围规则。<-在环境中执行搜索,因此有点难于解释。
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.
编辑:在对@Dirk和@Hadley的尊重中,听起来好像是分配给全局环境的适当方式(当你知道你想要的时候),而<<-是“提升”到更大范围的适当方式。
#3
0
As pointed out by @John in his answer, assign lets you specify the environment specifically. A specific application would be in the following:
正如@John在他的回答中指出的,赋值允许您明确指定环境。具体的申请如下:
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.
我们同时使用< <和赋值。请注意,如果您想使用<< <-来分配到顶层函数的环境,您需要声明 初始化变量。但是,通过assign,您可以使用parent.frame(1)来指定封装环境。< p>
#1
18
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):
托马斯·拉姆利(Thomas Lumley)在《r-help》(r-help)杂志上的一篇精彩文章中回答了这个问题。<<-是关于封闭环境的,所以你可以这样做(同样,我在这篇文章中引用了他4月22日的文章):
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:
这是<< <- as "super-assignment"在词法上的合理使用。而不仅仅是在全球环境中进行分配。为此,托马斯选择了以下字眼:
The Evil and Wrong use is to modify variables in the global environment.
恶意和错误的用法是修改全局环境中的变量。
Very good advice.
非常好的建议。
#2
2
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.
我从来没有在实践中这样做过,但是在我看来,为精确地指定环境而赋值可以赢得很多分数,甚至不需要考虑R的范围规则。<-在环境中执行搜索,因此有点难于解释。
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.
编辑:在对@Dirk和@Hadley的尊重中,听起来好像是分配给全局环境的适当方式(当你知道你想要的时候),而<<-是“提升”到更大范围的适当方式。
#3
0
As pointed out by @John in his answer, assign lets you specify the environment specifically. A specific application would be in the following:
正如@John在他的回答中指出的,赋值允许您明确指定环境。具体的申请如下:
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.
我们同时使用< <和赋值。请注意,如果您想使用<< <-来分配到顶层函数的环境,您需要声明 初始化变量。但是,通过assign,您可以使用parent.frame(1)来指定封装环境。< p>