r - 为什么函数A主体中的变量查找从全局环境中获取值,而不从调用A的函数B中获取值?

标签 r call environment

我定义了一个函数:

.get <- function( o, ...) {
    p <- match.call( expand.dots = 0)$...
    cat( sprintf( 'In .get, it is %s.\n', eval( tail( p, 1)[[ 1]])))
    fn <- switch( typeof( o), list =, environment = `[[`, 'S4' = '@', `[`)
    if( length( p)) eval( as.call( c( fn, quote( o), p))) else o # Here when true, I compose a call based on p.
}

然后我尝试如下:
it <- 1
m <- matrix( seq( 9), 3)
sapply( seq( 3), function( it) {
    cat( sprintf( 'In sapply, it is: %s.\n', it))
    .get( m, , it)
})
sapply( seq( 3), function( it) .get( m, , it))

输出:
In sapply, it is: 1.
In .get, it is 1.
In sapply, it is: 2.
In .get, it is 1.
In sapply, it is: 3.
In .get, it is 1.
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

但是预期的输出是:
In sapply, it is: 1.
In .get, it is 1.
In sapply, it is: 2.
In .get, it is 2.
In sapply, it is: 3.
In .get, it is 3.
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

那么,为什么it不是1到3(在函数被调用的地方具有的值),而是总是在全局环境中分配的值(即1)呢?

最佳答案

您是否在全局环境中与get一起定义了it?如果是这样,那么这可能是一个范围界定问题。请参阅herehere进行出色的讨论。

从第一个链接看这个例子:

 a = 1
 b = 2

 fun <- function(x){ a + b*x }

 new.fun <- function(x){
 a = 2
 b = 1
 fun(x)
 }

 new.fun(2)

如果在fun中调用的new.fun使用全局环境中的ab,则我们期望new.fun(2)的结果为1+2*2=5,而如果使用函数new.fun中定义的参数,则它应该为2+1*2=4。现在,大多数人期望结果为4,但结果为5。为什么?因为fun是在全局环境中定义的,所以全局变量ab对于fun很重要。要看到这一点,您可以使用str(fun)查看该函数的结构,该结构将揭示一个环境已附加到该函数上。使用list(environment(fun))查看该环境,您将看到该函数“记住”它是在全局环境中定义的。因此,函数fun将首先在该处查找以找到参数ab

为了解决这个问题,已经提出了许多解决方法,如果您对词法作用域进行谷歌搜索,则可以找到其中一些方法。有关背景信息,Hadley Wickam的下一本书在环境方面有出色的章节,请参见here。有关可能的解决方案,请参见here。解决问题的一种方法是覆盖环境。例如,
 new.fun2 <- function(x){
 a = 2
 b = 1
 environment(fun) = environment()
 fun(x)
 }

 new.fun2(2)

现在使用父环境(而不是全局环境)中定义的a=2, b=1给出4作为答案。我敢肯定,还有很多更优雅的解决方案。

也就是说,在您的情况下,使用
 sapply( seq( 3), function(it) {
   cat( sprintf( 'In sapply, it is: %s.\n', it))
   environment(.get) <- environment()
   .get( m, , it)
 })

作品。

关于r - 为什么函数A主体中的变量查找从全局环境中获取值,而不从调用A的函数B中获取值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23234640/

相关文章:

r - 让 dplyr 变异使用公式

r - 在 R 中绘制标准误差

r - 通过将一个变量拆分为多个变量来创建新列(在 R 中)

lua - 为什么在 load() 编译的函数内部调用的函数的 _ENV 使用 _G 作为其 _ENV,而不是提供给 load() 的 env arg?

r - 有没有办法在R函数which.max()中的联系之间进行随机抽样?

c# - C#SIP音频和视频通话

C# 从另一个窗体(radform)调用函数

python - 在Python中从子类调用父类(super class)方法

node.js process.env 无法在命令行中工作

php - mysqli_fetch_assoc()需要参数/调用成员函数bind_param()错误。如何获取并修复实际的mysql错误?