【问题标题】:Is in case of R functions a parent's parent environment of an environment also parent to the environment?在 R 函数的情况下,环境的父环境是否也是环境的父环境?
【发布时间】:2020-08-28 06:50:40
【问题描述】:

假设,我创建了环境 (E) 的父级父级环境 (E2

怎么了?请参阅下面可重现示例中的最后一行,其中print(parent-parent) 产生

# [1] FALSE # I would expect a TRUE here!!

来自文档?parent.env

如果一个人跟随通过反复调用找到的一系列外壳 parent.env 来自任何环境,最终到达空 环境emptyenv(),不能分配任何东西。

subfun0 <- function() {
  e <- parent.frame()
  attr(e, "name") <- "my_env"
  assign("my_env", 1,
         envir = parent.frame(),
         inherits = FALSE, immediate = TRUE)
  return(NULL)
}

subsubfun <- function() {
  print("  subsubfun")
  print("  =========")
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  # print(parent.env(env)) # <environment: R_GlobalEnv>??
  return(NULL)
}

subfun <- function() {
  print(" subfun")
  print(" ======")
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  subsubfun()
  return(NULL)
}

fun1 <- function() {
  print("fun1")
  print("====")
  subfun0()
  print(exists("my_env"))
  print(exists("my_env", parent.frame()))
  env <- parent.frame()
  print(exists("my_env", parent.env(env)))
  subfun()
  return(NULL)
} 


fun1()
# [1] "fun1"
# [1] "===="
# [1] TRUE #     OK
# [1] FALSE
# [1] FALSE
# [1] " subfun"
# [1] " ======"
# [1] FALSE
# [1] TRUE #     OK
# [1] FALSE
# [1] "  subsubfun"
# [1] "  ========="
# [1] FALSE
# [1] FALSE
# [1] FALSE #    I would expect a TRUE here!!

【问题讨论】:

    标签: r function


    【解决方案1】:

    问题在于您实际上是在全局环境中定义所有函数,因此它们的父级是全局环境。

    如果你在其他函数中定义你的函数,你会得到你所期望的。 看下面的例子。

    (我还创建了一个打印所有父环境直到全局环境的函数)

    env_genealogy <- function(env){
        
        while(!identical(env, globalenv())){
            
            env <- parent.env(env)
            print(env)
            
        }
        
    }
    
    
    
    fun1 <- function() {
        subfun0 <- function() {
            
            print(" subfun0")
            print(" ======")
            
            env_genealogy(environment())
            
            e <- parent.frame()
            attr(e, "name") <- "my_env"
            assign("my_env", 1,
                         envir = parent.frame(),
                         inherits = FALSE, immediate = TRUE)
            return(NULL)
        }
        
        
        subfun <- function() {
            
            subsubfun <- function() {
                print("  subsubfun")
                print("  =========")
                
                env_genealogy(environment())
                
                print(exists("my_env"))
                print(exists("my_env", parent.frame()))
                env <- parent.frame()
                print(exists("my_env", parent.env(env)))
                # print(parent.env(env)) # <environment: R_GlobalEnv>??
                return(NULL)
            }
            
            print(" subfun")
            print(" ======")
            
            env_genealogy(environment())
            
            print(exists("my_env"))
            print(exists("my_env", parent.frame()))
            env <- parent.frame()
            print(exists("my_env", parent.env(env)))
            subsubfun()
            return(NULL)
        }
        
        
        
        print("fun1")
        print("====")
        
        env_genealogy(environment())
        
        subfun0()
        print(exists("my_env"))
        print(exists("my_env", parent.frame()))
        env <- parent.frame()
        print(exists("my_env", parent.env(env)))
        subfun()
        return(NULL)
    } 
    
    
    fun1()
    
    [1] "fun1"
    [1] "===="
    <environment: R_GlobalEnv>
    [1] " subfun0"
    [1] " ======"
    <environment: 0x000001b0e4b124d8>
    <environment: R_GlobalEnv>
    [1] TRUE
    [1] FALSE
    [1] FALSE
    [1] " subfun"
    [1] " ======"
    <environment: 0x000001b0e4b124d8>
    attr(,"name")
    [1] "my_env"
    <environment: R_GlobalEnv>
    [1] TRUE
    [1] TRUE
    [1] FALSE
    [1] "  subsubfun"
    [1] "  ========="
    <environment: 0x000001b0e552add0>
    <environment: 0x000001b0e4b124d8>
    attr(,"name")
    [1] "my_env"
    <environment: R_GlobalEnv>
    [1] TRUE
    [1] TRUE
    [1] TRUE
    NULL
    

    更多详情请关注here


    举个简单的例子,你可以看看这个:

    a <- function(){
        
        i
        
    }
     
    a()
    > #> Error in a() : object "i" not found
    
    b <- function(){
        
        i <- 1
        
        a()
        
    }
    b()
    > #> Error in a() : object "i" not found
     
    d <- function(){
        
        i <<- 1
        a()
        
    }
    d()
    #> [1] 1
    rm(i)
     
     
    f <- function(){
        
        g <- a
        i <- 2
        g()
        
    }
    f()
    #> Error in g() : object "i" not found
    
    h <- function(){
        
        l <- function() i
        i <- 2
        l()
        
    }
    h()
    #> [1] 2
    

    当您调用 a() 时,您会收到错误消息,因为未定义 i

    即使您在b() 中定义i,也会出现相同的错误,因为b 的环境未与a 共享。这是你的情况。

    d() 有效,因为我们将i 分配给具有&lt;&lt;- 的全局环境。

    f() 不起作用:即使我们在f 中定义了g,我们也复制了a,它也复制了它的父环境。

    我们在h() 中得到一个结果,因为l() 是在内部定义的。这就是我在回答中向您展示的情况。

    【讨论】:

    • 谢谢,非常明确的答案。对我来说,这仍然违反直觉。
    • 或许你也知道this问题的答案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 2018-10-20
    相关资源
    最近更新 更多