[英]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.