我想更好地了解environments,closures和frames如何相关。我知道函数闭包包含一个环境,环境包含一个框架和一个外壳,并且框架包含变量,但我对它们如何与另一个进行交互有点模糊。环境,(en)封闭和框架如何相关?
也许一个函数调用过程中发生的事情的例子会有所帮助吗?或者也许是一个图?
我想更好地了解environments,closures和frames如何相关。我知道函数闭包包含一个环境,环境包含一个框架和一个外壳,并且框架包含变量,但我对它们如何与另一个进行交互有点模糊。环境,(en)封闭和框架如何相关?
也许一个函数调用过程中发生的事情的例子会有所帮助吗?或者也许是一个图?
UPDATE R-郎限定environment
为具有帧。我倾向于将帧视为堆栈帧,而不是从名称到值的映射 - 但是当然有data.frame
将列名映射到向量(然后一些...)。我认为大部分的困惑来自于最初的S语言(还有S-Plus)没有环境对象这一事实,因此所有的“框架”本质上都是环境对象,除了它们只能作为一部分的调用堆栈。
例如,在S-Plus中,sys.nframe
的文档说“sys.nframe返回所有帧列表中当前帧的数字索引。” ...这听起来极像是堆栈帧我...你可以阅读更多有关堆栈帧这里:http://en.wikipedia.org/wiki/Call_stack#Structure
我扩大了下面的一些解释和使用“堆栈帧”一致(我希望)。
结束时更新
我解释他们是这样的:
的环境变量名映射到值的对象。每个映射称为绑定。价值可以是实际价值或承诺。一个环境有一个父环境(除了空的环境)。当您在环境中查找符号并找不到时,还会搜索父环境。
承诺是一个未评估的表达和评估表达的环境。当评估承诺时,它将被替换为生成的值。
闭包是一个功能和环境的函数,定义如下lm
的函数将有统计命名空间环境和用户定义的函数将有全球环境 - 但其他功能g
中定义的函数f
作为其环境的本地环境为g
。
堆栈帧(或激活记录)表示调用堆栈上的条目。每个堆栈帧都具有执行该函数的本地环境以及函数调用的表达式(以便sys.call
工作)。
当执行一个函数调用时,会创建一个本地环境,它的父级设置为闭包的环境,参数与函数的形式参数相匹配,并且这些绑定被添加到本地环境中(作为承诺)。不匹配的形式参数被赋予函数的缺省值(承诺)(如果有的话)并被标记为缺失。然后用这个本地环境和调用表达式创建一个堆栈框架。堆栈框架被压入调用堆栈,然后在本地环境中评估函数的主体。
...所以身体内的所有符号将在本地环境抬头(正式的参数和局部变量),如果在父环境(这是封闭环境)未发现和父母的家长环境等等,直到找到。
请注意,在这种情况下,父堆栈框架的环境是NOT。该parent.frame
,sys.frame
函数获取调用堆栈上的环境 - 即,呼叫者的环境和调用者的调用者的环境等等
# Here match.fun needs to look in the caller's caller's environment to find what "x" is...
f <- function(FUN) match.fun(FUN)(1:10)
g <- function() { x=sin; y="x"; f(y) }
g() # same as sin(1:10)
# Here we see that the stack frames must also contain the actual call expression
f <- function(...) sys.call()
g <- function(...) f(..., x=42)
g(a=2) # f(..., x = 42)
请问this extended description by John Fox解决您的问题?
它有很好的图表,但没有小马。
在Fox & Weisberg book, "An R Companion to Applied Regression" (2011)也有说明,从页码开始。 417或第8.9.1节。我认为上面的PDF虽然比较老,但可能只是提供信息,如果不是更多的话(因为图表)。 F & W是一本好书,我已经插入了a couple之前的时间,对于other useful stuff。 FWIW,在“R in a Nutshell”一书中我没有找到任何有用的见解。不过,我还没有任何钱伯斯的书。
@DirkEddelbuettel:这不是谦虚;小马很混乱。我还没有读过。我会拿起一份副本并回答我自己的问题。 –
我的答案接近您要查找的内容,还是应该澄清其中的任何部分? – Tommy