理解R中的词汇范围

tch*_*rty 17 scope r

我正在阅读这篇关于评估R编程语言设计的文章(非版权副本),并且我无法理解关于词法作用域(或其缺失)的特定示例.

在第4页,作者提供了以下使用该with函数的示例:

with(formaldehyde, carb*optden)
Run Code Online (Sandbox Code Playgroud)

他们继续说:

精明的读者会注意到上面的例子与我们声称R是词汇范围的冲突相冲突.通常情况下,R在词汇上被限定到不是这样的程度.R首先是一种动态语言,具有对运行程序的数据和表示的完全反射访问.在上面的例子中,通过反射操纵环境来避免词法范围的实现.这是通过惰性评估,动态名称查找以及将代码转换为文本和返回的能力的组合来完成的:

with.default <- function(env, expr, ...)
  eval(substitute(expr),env, enclose=parent.frame())
Run Code Online (Sandbox Code Playgroud)

该函数用于substitute检索其第二个参数的未评估解析树,然后eval在通过将第一个参数与词法封闭环境组合而构成的环境中对其进行评估.' ...'用于丢弃任何其他参数.

with在这种情况下,如何使用函数违反词法范围的原则?

G. *_*eck 27

通常在R词汇范围的上下文中讨论意味着在函数的父环境中查找函数中的自由变量(即函数中使用但未在函数中定义的变量),而不是环境调用者(也称为父框架)但没有自由变量,with.default因此该示例并未说明在这种意义上违反词法范围.

例如,这说明了词法范围:

x <- 1
f <- function() x
g <- function() { x <- 0; f() }
g() # 1
Run Code Online (Sandbox Code Playgroud)

答案是1,因为1,所述环境定义f定义.假如中的R用动态作用域而非词法作用域的答案将是0(使用调用者的环境).我们可以说明R如何模拟动态范围,如下所示:

f <- function() eval.parent(quote(x))
g() # 0
Run Code Online (Sandbox Code Playgroud)

添加:

在下面的评论中,@ hadley建议作者可能一直在指的是第二个实际论证with.default并未在词汇上进行评估,这种解释似乎很可能.不是相对于周围的词汇环境进行评估,而是将第二个实际参数作为表达式with.default读入with.default函数substitute,然后使用相对于第一个参数进行评估eval.有一些问题是词汇范围的定义应该是什么,因为它很少被定义,即使在广泛讨论时,但与R相关的典型讨论将其称为自由变量的处理.例如,参见Gentleman&Ihaka.

  • 我认为它确实说明了对词法范围的违反,因为函数参数的评估通常也是词法的。词法范围不仅仅是自由变量。 (2认同)