了解封闭环境

时间:2016-08-11 13:20:20

标签: r

我有以下代码

new_counter <- function(){
  ij <- 0
  function(){
    ij <<- ij+1
    ij
  }
}

counter_one <- new_counter()
counter_two <- new_counter()

counter_one()
counter_one()

来自tutorial

他们写道:

  

计数器通过不修改来绕过“新开始”限制   当地环境中的变量。由于进行了更改   不变的父(或封闭)环境,它们被保留   跨职能电话。

我认为这是:new_counter函数是在.GlobalEnvenclosing environment)以及counter_one函数中创建的。但execution environment new_counter函数比counter_one函数高一级。这通常是暂时的,但这次不是因为我们有一个机箱功能。

但我怎么能看到'this'封闭环境并且它们相隔一层?使用(pryr)where环境为全局环境提供两种功能。

编辑: 他们谈论两种不同的环境:

  1. '在当地环境中'
  2. '在一个没有联系的父母环境中'
  3. 所以对我来说,这是两种不同的环境,但如果它们不同,它们可能有不同的名称!我该怎么知道这个名字?使用

    where("new_counter")
    where("counter_one")
    

    既可以提供全球环境,但查看上面的枚举,必须是两个不同的。

2 个答案:

答案 0 :(得分:2)

这应该有希望澄清正在发生的事情。请注意,new_counter的封闭环境是全局环境,但counter_onecounter_two的环境是new_counter的两个执行实例中的环境。通常,函数的封闭环境是它的词汇环境(定义它的环境),但在某些情况下会有所不同。

new_counter <- function(){
  e <- environment()
  print(e)
  ij <- 0
  function(){
    ij <<- ij+1
    ij
  }
}

counter_one <- new_counter()  # A
counter_two <- new_counter()  # B

counter_one()
counter_one()

environment(new_counter) # global environment

environment(counter_one) # see output of A
environment(counter_two) # see output of B

这是一个更简单的示例,它显示函数可以位于一个环境中,但其封闭环境可以是不同的环境。在这种情况下,f处于全球环境中;但是,它的封闭环境是e,而不是全球环境。

e <- new.env()
e$x <- 1
x <- 2
f <- function() x
environment(f) <- e
f() 
## [1] 1

实际上有几种环境可以考虑。让我们在上一个示例中为f添加一些工具。

f <- function() {
       ee <- environment()
       print(ee)
       x
}
e <- new.env()   
e$x <- 1   
x <- 2
environment(f) <- e
f() # displays ee and then the value of x which is 1

这些是环境:

  • f的封闭环境是e,因为我们这样设置

  • 词汇环境是f所处的环境。这里是全球环境。通常,词汇环境和封闭环境是相同的,但是因为我们重置了f的封闭环境,在这种情况下它们是不同的。

  • 函数f中的执行环境在运行时。在这种情况下,它是eef完成后,执行环境将被销毁,除非仍然有来自外部的指针。每次运行f时,都会创建一个新的执行环境,以便ee每次运行f时都会获取一个新值。

因此,在此示例中,每次e运行时都会有f,全局环境和一个执行环境。

这里有一些讨论:http://adv-r.had.co.nz/Environments.html

更新一些澄清。

答案 1 :(得分:1)

如果没有pryr,您可以看到类似以下内容的环境:

environment(counter_one)
# <environment: 0x00000000078be648>
environment(counter_two)
# <environment: 0x00000000078bf148>
ls(env=environment(counter_two))
# [1] "ij"
counter_one()
# [1] 1
get("ij", envir = environment(counter_one))
# [1] 1
get("ij", envir = environment(counter_two))
# [1] 0

此外,您可以更改该环境中变量的值:

assign("abc", 123, envir = environment(counter_two))
ls(envir = environment(counter_one))
# [1] "ij"
ls(envir = environment(counter_two))
# [1] "abc" "ij"