我正在阅读有关评估R编程语言的设计的this paper(ungated copy),并且无法理解有关词法作用域(或缺少词法作用域)的特定示例。
在第4页上,作者提供了以下使用with
函数的示例:
with(formaldehyde, carb*optden)
他们接着说:
精明的读者会注意到上面的示例发生了冲突
我们声称R是词法范围的。通常,R是
从词法上讲,范围一直到不是。 R首先是动态的
语言,可以全面反映正在运行的程序的数据,以及
表示。在上面的示例中,用
通过反思性地操作来规避词汇范围
环境。这是通过结合惰性评估,动态
名称查找,并能够将代码转换为文本并返回:
with.default <- function(env, expr, ...)
eval(substitute(expr),env, enclose=parent.frame())
该函数使用
substitute
来检索未评估的分析树它的第二个参数,然后在环境中用
eval
对其求值通过将第一个参数与词汇组成
封闭的环境。 “
...
”用于舍弃所有其他论点。
在这种情况下,使用
with
函数如何违反词汇作用域的原理? 最佳答案
通常,在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
函数,然后使用eval
相对于第一个参数求值。关于词汇作用域的定义应该是什么样的问题,即使在进行了广泛讨论时也很少定义,但有关R的典型讨论将其称为自由变量的处理。参见例如Gentleman & Ihaka。关于r - 了解R中的词法作用域,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20766649/