R中`substitute`函数的行为令人困惑

6

大家好,这让我很疯狂。

以下内容按预期工作:

eobj <- substitute(obj <- list(a, b), list(a = 32, b = 33))
eval(eobj)
obj
[[1]]
[1] 32

[[2]]
[1] 33

现在,请尝试这个:
efun <- substitute(fun <- function() a+ b, list(a = 32, b = 33))
str(efun)
# language fun <- function() 32 + 33  
eval(efun)
fun
# function() a+ b

这里发生了什么?到底是怎样让eval获取表达式的原始形式的?
1个回答

8
因为当你打印fun时实际上会打印函数的源代码(参见attributes(fun)),这不会被substitute修改。
请注意,当您在全局工作区中定义ab时,函数结果是相同的。
您可以通过body(fun)查看函数的实际代码。
或者进行比较:
print.function(fun, useSource=FALSE)
# function () 
# 32 + 33
print.function(fun, useSource=TRUE) # Which is default
# function() a+ b

是的,这确实是源代码。但是,我仍然困惑,源代码来自哪里?乐趣的来源与对象本身分开保留吗?表达式“efun”没有任何参考来源。“eval”没有直接访问原始定义。 - VitoshKa
我猜想在substitute起作用之前,源代码已经被设置好了。这里的function会创建一个带有源代码参数的表达式(语言?),然后substitute将表达式内部的ab的值替换为正确的值,但不会改变源代码。 - Marek
2
attr(fun, "source") 显示函数保留的源代码以及 print 实际打印出来的内容。如果没有 "source" 属性,则 print 将显示实际函数。因此,attr(fun, "source") <- NULL 将导致 print 显示实际函数而不是 "source" 属性的内容。另外,options(keep.source = FALSE) 可用于完全关闭此行为,在这种情况下,您的函数将首先不会获得 "source" 属性。 - G. Grothendieck
@Marek 看起来是这样。但这意味着在函数分配给 fun 之前,在解析时设置了源。那么它在此期间存储在哪里?efun 没有源属性。这可能是我们最好问 R 核心。 - VitoshKa
1
@VitoshKa,如果你执行save(efun, file="test.txt", ascii=TRUE)并查看这个文件,你会发现其中包含了带有ab的原始代码。 - Marek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接