首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >操作函数的封闭环境

操作函数的封闭环境
EN

Stack Overflow用户
提问于 2019-01-15 09:54:30
回答 2查看 67关注 0票数 1

我试图更好地理解闭包,特别是关于函数的作用域和如何使用它的封闭环境的详细信息。

基于rlang::fn_env()上帮助页面的rlang::fn_env()部分,我了解到,函数始终可以访问其作用域中的所有变量,并且其封闭环境属于该作用域。

但是,为什么不能“事后”操作闭包环境的内容,即在函数创建之后?

通过R的词法范围,当我把bar()放在它的封闭环境中时,它不应该找到x吗?

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

发布于 2019-01-15 10:07:14

啊,我想我把它弄下来了。

它与函数的形式参数的结构有关:

如果参数是在没有默认值的情况下定义的,则R会在调用函数时发出抱怨,而不指定函数,即使在技术上它可能能够在其范围内查找它。

即使不想定义默认值,也可以通过rlang::fn_fmls()在运行时设置缺省值。

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2019-01-15 10:17:15

由于我不熟悉rlang库,所以我不能真正学习您的示例,但我认为R中闭包的一个很好的示例是:

代码语言:javascript
复制
bucket <- function() {
    n <- 1
    foo <- function(x) {
        assign("n", n+1, envir = parent.env(environment()))
        n
    }
    foo
}
bar <- bucket()

因为bar()是在bucket的函数环境中定义的,所以它的父环境是bucket,因此您可以在那里携带一些数据。每次运行它时,都会修改bucket环境:

代码语言:javascript
复制
bar()
[1] 2
bar()
[1] 3
bar()
[1] 4
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54196446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档