理解R中的词汇范围

时间:2013-12-24 20:55:14

标签: r scope

我正在阅读this paperungated copy)关于评估R编程语言的设计,并且我无法理解关于词法作用域(或其缺失)的特定示例。

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

with(formaldehyde, carb*optden)

他们接着说:

  

精明的读者会注意到上面的例子发生了冲突   我们声称R是词汇范围的。通常情况下,R是   词汇量上限到它不是。 R首先是动态的   语言,可以完全反射访问正在运行的程序的数据和   表示。在上面的例子中,执行了   通过反思操纵词汇来回避词汇范围   环境。这是通过懒惰评估,动态组合完成的   名称查找,以及将代码转换为文本和返回的能力:

with.default <- function(env, expr, ...)
  eval(substitute(expr),env, enclose=parent.frame())
  

该函数使用substitute来检索未评估的解析树   它的第二个参数,然后在环境中使用eval进行评估   通过用词汇构成第一个参数构成   封闭的环境。 “...”用于丢弃任何其他内容   参数。

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

1 个答案:

答案 0 :(得分:26)

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

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

x <- 1
f <- function() x
g <- function() { x <- 0; f() }
g() # 1

答案是1,因为在f 定义的环境中定义了1。如果R使用动态范围而不是词法范围,则答案将为0(使用环境)的来电者)。我们可以说明R如何模仿这样的动态范围:

f <- function() eval.parent(quote(x))
g() # 0

增加:

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