操纵功能的封闭环境

时间:2019-01-15 09:54:31

标签: r scope closures rlang

我试图更好地了解closures,尤其是有关函数的作用域以及如何使用其封闭环境的详细信息>

基于Description帮助页面的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

class AppDelegate: NSObject, NSApplicationDelegate, CLLocationManagerDelegate {
  let locationManager = CLLocationManager()
  func applicationDidFinishLaunching(_ aNotification: Notification) {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
  }
 func scanLocationRequest{
   locationManager.startUpdatingLocation()
   // Call this when a notification receives.
 }
 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let currentLocation = locations.last
    locationManager.stopUpdatingLocation()
    sendLocationReport(currentLocation: currentLocation!)
 }

}

2 个答案:

答案 0 :(得分:0)

啊,我想我现在明白了。

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

如果定义的参数没有默认值,则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

答案 1 :(得分:0)

由于我不熟悉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