簡體   English   中英

操縱功能的封閉環境

[英]Manipulating enclosing environment of a function

我試圖更好地理解閉包 ,尤其是有關函數作用域以及如何使用其封閉環境的詳細信息

基於rlang::fn_env()的幫助頁面的“ Description部分,我了解到,一個函數始終可以訪問其作用域中的所有變量,並且其封閉環境屬於該作用域。

但是,為什么不能“在事實之后”(即在函數創建之后)操縱封閉環境的內容呢?

通過R的詞法作用域,當我放入x的封閉環境時, 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

嗯,我想我現在明白了。

它與函數形式參數的結構有關:

如果定義的參數沒有默認值,則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

我不熟悉您的示例,因為我不熟悉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] 4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM