我对R很新,但是来自Scheme--它也是词法范围并且有闭包 - 我希望能够在闭包中改变外部变量。
,例如
foo <- function() {
s <- 100
add <- function() {
s <- s + 1
}
add()
s
}
cat(foo(), "\n") # prints 100 and not 101
我希望foo()
返回101,但它实际上返回100:
$ Rscript foo.R
100
我知道Python有global
关键字来声明变量的范围(虽然不能使用这个例子)。 R需要类似的东西吗?
我做错了什么?
更新
啊,add
我在创建一个新的局部变量s
是否会影响外部s
的问题?如果是这样,我如何在不创建局部变量的情况下改变s
?
答案 0 :(得分:3)
使用<<-
运算符在add()
函数中进行分配。
来自?"<<-"
:
运算符
<<-
和->>
通常仅在函数中使用,并导致通过父环境搜索所分配变量的现有定义。如果找到这样的变量(并且其绑定未被锁定),则重新定义其值,否则在全局环境中进行赋值。请注意,它们的语义与S语言的语义不同,但与R的范围规则结合使用时,请参阅“R语言定义”手册以获取更多详细信息和示例。
答案 1 :(得分:3)
您还可以使用assign
并使用envir
参数精确定义范围,在<<-
函数中的工作方式与add
的工作方式相同,但是意图更清楚一点:
foo <- function() {
s <- 100
add <- function() {
assign("s", s + 1, envir = parent.frame())
}
add()
s
}
cat(foo(), "\n")
当然,在R中这种事情的更好方法是让你的函数返回它修改的变量(或变量),并明确地将它们重新分配给原始变量:
foo <- function() {
s <- 100
add <- function(x) x + 1
s <- add(s)
s
}
cat(foo(), "\n")
答案 2 :(得分:2)
以下是一种比assign
或<<-
方法更安全的方法:
foo <- function() {
e <- environment()
s <- 100
add <- function() {
e$s <- e$s + 1
}
add()
s
}
foo()
<<-
分配可能会导致问题,如果您不小心拼错了变量名称,它仍会执行某些操作,但它不会是您所期望的,并且很难找到问题的根源。如果您想将add函数移动到另一个函数内部,或者从另一个函数调用它,那么assign
方法可能会很棘手。总体上最好的方法是不让函数修改变量超出它们自己的范围,并让函数返回任何重要的东西。但是当不可能时,上面的方法使用词法作用域来访问环境e
,然后分配到环境中,因此它将始终专门分配给该函数,从不在上面或下面。