apply()和forceAndCall()忽略parent.frame()中的get() [英] apply() and forceAndCall() ignoring get() from parent.frame()

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

问题描述

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

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.第二条打印语句显示,由于inherits = TRUE,在parent.frame(2)中找到了v.最后一个是谜.

似乎apply忽略了get(envir = parent.frame()).我将此追溯到apply()中的函数forceAndCall().我是否缺少某些东西或这是一个错误?

在实际应用中,v仅在函数f的调用环境中定义(即在parent.frame()或更高版本中),而从未在parent.env()中定义.

解决方案

此处的关键问题是调用环境以及get(inherits=TRUE)处理它们的方式.对于初学者,我建议您阅读Hadley的函数环境.

更具体地说,人们必须了解函数的封装和调用环境,以了解发生了什么事情.

v是在函数f调用环境中定义的-从函数的执行环境来看-第一个print语句中的parent.frame(1L)和最后两个打印语句中的parent.frame(2L)./p>

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

我们真正需要的是一个get函数,该函数不会在父包围环境的层次结构中搜索v,而是在父调用环境的层次结构中进行搜索.而这正是dynget()的作用.

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

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

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()

with:

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

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.

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?

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().

解决方案

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 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.

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.

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() is somewhat experimental and to be used inside another function. It looks for an object in the callers, i.e., the sys.frame()s of the function. Use with caution

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()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆