我正在阅读this paper(ungated 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
函数违反了词法范围的原则?
答案 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。