本文介绍了apply() 和 forceAndCall() 忽略来自 parent.frame() 的 get()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么这段代码在最后一行打印失败:

I don't understand why this code is failing on the last printed line:

f <- function(x) get('v', envir = parent.frame(), inherits = TRUE)

run <- function() {

  v <- 'test variable'

  print(f())
  print((function() f())())
  print(apply(X = data.frame(1:2), MARGIN = 1, f))
}
run()

与:

 Error in get("v", envir = parent.frame(), inherits = TRUE) : 
  object 'v' not found 

第一条打印语句显示在parent.frame(1) 中找到了v.第二个打印语句显示 v 由于 inherits = TRUE 而在 parent.frame(2) 中找到.最后一个是谜.

The first print statement shows that v is found in parent.frame(1). The second print statement shows that v is found in parent.frame(2) due to inherits = TRUE. The last one is the enigma.

似乎 apply 忽略了 get(envir = parent.frame()).我将其追溯到 apply() 中的 forceAndCall() 函数.我错过了什么还是这是一个错误?

Seems that apply is ignoring the get(envir = parent.frame()). I traced this back to function forceAndCall() within apply(). Am I missing something or is this a bug?

在实际应用中,v只定义在函数f的调用环境中(即parent.frame()或以上)),但永远不会在 parent.env() 中.

In real application, v is only defined in the calling environment of the function f (i.e. in parent.frame() or above), but never in parent.env().

推荐答案

这里的关键问题是调用环境以及 get(inherits=TRUE) 处理它们的方式.首先,我建议您阅读 Hadley 的函数环境.

The key issue here are the calling environments and the way get(inherits=TRUE) handles them. For starters, I suggest one reads Hadley's Function environments.

更具体地说,必须了解函数的封闭和调用环境才能了解正在发生的事情.

More specifically, one has to understand function's enclosing and calling environments to understand what is going on.

v定义在函数f的调用环境中,也就是——从函数的执行环境来看——parent.frame(1L) 在第一个打印语句中,parent.frame(2L) 在最后两个打印语句中.

v is defined in the function f calling environment, which is -- looking from the function's execution environment -- parent.frame(1L) in the first print statement, and parent.frame(2L) in the last two print statements.

我认为如果我提供带有 inherits=TRUEenvir=parent.frame(1L)get 函数将遍历 envir=parent.frame(1L)code>parent.frame() 层次结构并最终在父调用环境之一中找到v.它不是.实际上,它从一个提供的 envir 环境开始,并在 v 的父 封闭 环境中查找.对于第二条print语句,parent.frame(1L)的封闭父环境正是定义了v的地方,但是在最后一条print语句中,封闭父环境是vparent.frame(1L)base 命名空间,其中定义了 apply.在此之上的封闭父环境是全局环境.所以 v 没有找到.

I thought that if I supply envir=parent.frame(1L) with inherits=TRUE, the get function would traverse the parent.frame() hierarchy and eventually find v in one of the parent calling environments. It does not. In reality it starts from the envir environment one supplies and looks in the parent enclosing environments for v. For the second print statement, the enclosing parent environment of parent.frame(1L) is exactly where v is defined, but in the last print statement, the enclosing parent environment of parent.frame(1L) is the base namespace where apply is defined. Enclosing parent environment on top of that is the global environment. So v is not found.

我们真正需要的是一个 get 函数,它不会在父封闭环境层次结构中搜索 v,而是在父调用环境层次结构中搜索.而这正是 dynget() 所做的.

What we really need is a get function that doesn't search in the parent enclosing environments hierarchy for v, but in parent calling environments hierarchy. And that is exactly what dynget() does.

dynGet() 有点实验性,可以在另一个内部使用功能.它在调用者中寻找一个对象,即sys.frame()s 的函数.谨慎使用

此函数将遍历父调用环境sys.parents()sys.frame() 并在每个环境中查找v他们.所以 f <- function(x) dynGet('v', inherits = TRUE) 解决了这个问题.

This function will traverse the parent calling environments sys.parents() with sys.frame() and look for v in each of them. So f <- function(x) dynGet('v', inherits = TRUE) solves the problem.

这篇关于apply() 和 forceAndCall() 忽略来自 parent.frame() 的 get()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 17:25