我试图更好地理解闭包,特别是关于函数的作用域和如何使用它的封闭环境的详细信息。
基于rlang::fn_env()上帮助页面的rlang::fn_env()部分,我了解到,函数始终可以访问其作用域中的所有变量,并且其封闭环境属于该作用域。
但是,为什么不能“事后”操作闭包环境的内容,即在函数创建之后?
通过R的词法范围,当我把bar()放在它的封闭环境中时,它不应该找到x吗?
foo <- function(fun) {
env_closure <- rlang::fn_env(fun)
env_closure$x <- 5
fun()
}
bar <- function(x) x
foo(bar)
#> Error in fun(): argument "x" is missing, with no default发布于 2019-01-15 10:07:14
啊,我想我把它弄下来了。
它与函数的形式参数的结构有关:
如果参数是在没有默认值的情况下定义的,则R会在调用函数时发出抱怨,而不指定函数,即使在技术上它可能能够在其范围内查找它。
即使不想定义默认值,也可以通过rlang::fn_fmls()在运行时设置缺省值。
foo <- function(fun) {
env_enclosing <- rlang::fn_env(fun)
env_enclosing$x <- 5
fun()
}
# No argument at all -> lexical scoping takes over
baz <- function() x
foo(baz)
#> [1] 5
# Set defaults to desired values on the fly at run time of `foo()`
foo <- function(fun) {
env_enclosing <- rlang::fn_env(fun)
env_enclosing$x <- 5
fmls <- rlang::fn_fmls(fun)
fmls$x <- substitute(get("x", envir = env_enclosing, inherits = FALSE))
rlang::fn_fmls(fun) <- fmls
fun()
}
bar <- function(x) x
foo(bar)
#> [1] 5发布于 2019-01-15 10:17:15
由于我不熟悉rlang库,所以我不能真正学习您的示例,但我认为R中闭包的一个很好的示例是:
bucket <- function() {
n <- 1
foo <- function(x) {
assign("n", n+1, envir = parent.env(environment()))
n
}
foo
}
bar <- bucket()因为bar()是在bucket的函数环境中定义的,所以它的父环境是bucket,因此您可以在那里携带一些数据。每次运行它时,都会修改bucket环境:
bar()
[1] 2
bar()
[1] 3
bar()
[1] 4https://stackoverflow.com/questions/54196446
复制相似问题