lapply循环中的函数环境

时间:2017-08-08 09:08:43

标签: r function lapply environment

所以我遇到了这个与不同环境中存在的变量有关的问题,这让我很困惑,因为它不符合我对函数如何查找各种对象的理解。

我的玩具示例非常简单:我有一个函数foo接受一个参数jfoo生活在lapply循环函数内,并带有参数' i'。现在,i显然存在于lapply环境中(而不是全局环境中)。在lapply函数foo内调用时,很难找到i并抛出错误:

foo <- function(j){
 message('foo env: exists(j) ', exists('j'))
 message('foo env: exists(i) ', exists('i'))
 i
}

env.g <- environment()
invisible(lapply(1, FUN = function(i){
  message('global env: exists(i) ', exists('i', envir = env.g))
  message('lapply env: exists(i) ', exists('i'))
  message(' ')
  j <- i + 1

  foo(j)
   }
  ))

#global env: exists(i) FALSE
#lapply env: exists(i) TRUE

#foo env: exists(j) TRUE
#foo env: exists(i) FALSE
#Error in foo(j) : object 'i' not found

另一方面,当i存在于全球环境中时,foo就可以了:

i <- 10
foo()
#foo env: exists(j) TRUE
#foo env: exists(i) TRUE
#[1] 10

所以我之前的理解是,如果某个函数在自己的环境中没有看到变量,那么它将进入下一个变量(在我的第一个示例中为lapply,在第二个示例中为全局变量) ,直到它找到它。但是,它显然没有进入上面lapply的外循环......为什么?

2 个答案:

答案 0 :(得分:2)

我认为这是因为函数foo()是在定义函数的环境中进行评估的。在您的示例中,foo()在全局环境中定义,因此i不在范围内。如果您在匿名函数中定义foo(),则i似乎正确评估。

env.g <- environment()
invisible(lapply(1, FUN = function(i){
  message('global env: exists(i) ', exists('i', envir = env.g))
  message('lapply env: exists(i) ', exists('i'))
  message(' ')
  j <- i + 1

  foo <- function(j){
   message('foo env: exists(j) ', exists('j'))
   message('foo env: exists(i) ', exists('i'))
   i
  }

  foo(j)
   }
  ))

#global env: exists(i) FALSE
#lapply env: exists(i) TRUE

#foo env: exists(j) TRUE
#foo env: exists(i) TRUE

答案 1 :(得分:1)

有4种类型的环境与功能相关联。

当你跑步时:

rm(i)
lapply(1, foo)

甚至:

rm(i)
lapply(1, function(x) {
  i <- 42
  foo(x)
})

情况是:

lapply

  • 附上env:namespace:base

  • 绑定环境:package:base

  • 执行环境:动态创建,并附在.GlobalEnv

  • 致电环境:.GlobalEnv

foo

  • 附上(定义的地方):.GlobalEnv

  • 绑定(名称foo所在的位置):.GlobalEnv

  • 执行(包含在Calling env中):动态创建并封闭......我甚至不确定在哪里,但是当进入封闭环境链时,应该有执行环境lapply

  • 致电:同样,不太确定......但这不重要

但:
(可能)与直觉相反,通过上升调用堆栈找不到变量&#34; AKA 动态范围 (即:foo的exec env,(然后可能是某些中间环境),然后执行lapply的env(其中)我们会找到i <- 42),然后是.GlobalEnv),但直接在foo AKA 词汇范围 的封闭环境中,然后其封闭环境的链条绕过lapply的执行环境,因此找不到i,即使它刚刚在上面明确声明......