and*_*ewH 5 evaluation arguments r names scoping
运行后:
x <- as.name("aa")
aa <- 2
Run Code Online (Sandbox Code Playgroud)
在R中,为什么不呢
(x)
Run Code Online (Sandbox Code Playgroud)
返回2?为什么不呢
x <- as.name("aa")
aa <- 3
get(get(x))
Run Code Online (Sandbox Code Playgroud)
回来3?
我知道get()需要一个字符串,但我不明白为什么它不评估x,在里面找到字符串,然后得到它.在我看来,有时函数会对它们的参数进行这样的评估,有时它们却没有.例如,在第二个示例中,如果使用eval(x)替换get(get(x)),则eval()会计算x以查找名称,然后计算名称以查找3.
jor*_*ran 10
因为值x不是2,所以它是符号(或名称)aa.但是,如果你eval这样:
> eval(x)
[1] 2
Run Code Online (Sandbox Code Playgroud)
类似地,get(x)根本不起作用(即产生错误),因为根据文档get,它的第一个参数必须是an object name (given as a character string),其中括号用于区分它与符号/名称.
get 仅适用于字符参数:
> get("aa")
[1] 2
Run Code Online (Sandbox Code Playgroud)
而且symbol(我觉得不那么容易混淆name)不是一回事:
> identical("aa",as.name("aa"))
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
(as.name并as.symbol做同样的事情.)
有关"表达式评估"与"功能参数评估"区别的优秀解释,我在下面的评论中提到,请参阅@ MrFlick的答案.
我认为@joran的回答是正确的,但也许我可以尝试用不同的方式来解释.
(R中的"函数"本质上是身份函数.它回应了你传递的东西.它几乎就像不在那里.这些陈述将返回的内容之间没有区别
x #1
(x) #2
((x)) #3
Run Code Online (Sandbox Code Playgroud)
括号只是通过里面的值.您可以根据需要添加任意数量的括号,它不会更改返回的内容.评估者查看((x)),查看外括号,并知道只返回括号内的事物的值.所以现在它正在解析(x),并再次看到外括号,并且只返回括号内的值,即x.括号只是从内部传递值; 他们不评估它.
裸值x是名称(或符号).名称不是唯一与值相关联的.名称和值之间的映射因环境而异.这就是为什么必须在特定的上下文中评估名称才能获得值.考虑这些例子
aa <- 5
dd <- data.frame(aa=20)
x <- as.name("aa")
foo <- function(x) {aa<-10; eval(x)}
eval(x)
# [1] 5
foo(x)
# [1] 10
eval(x, dd)
# [1] 20
Run Code Online (Sandbox Code Playgroud)
这种行为实际上是非常需要的.这就是需要非标准评估工作的功能,例如
subset(mtcars, hp<100)
Run Code Online (Sandbox Code Playgroud)
当您使用R控制台时,它表现为REPL - 它读取您的输入,评估它,打印它,然后等待下一个输入.请注意,它只进行一级评估,评估在"当前"环境中进行.它不会递归计算表达式的返回值.所以,当你这样做
x <- as.name("aa")
x # identical to (x)
# aa
Run Code Online (Sandbox Code Playgroud)
当REPL进入评估步骤时,它会评估x指向名称的名称aa.而已.一级评估.aa随后不评估该名称.
?eval帮助页面中有一条说明如下:
eval在将其传递给求值程序之前计算当前作用域中的第一个参数
那里没有发生"双重"评估.它只是像R中的任何其他函数一样评估它的参数.举些例子
aa <- 5
bar <- function(x) print(x)
bar(aa+2)
# [1] 7
Run Code Online (Sandbox Code Playgroud)
它打印"7",而不是"aa + 2",因为该功能在打印之前已经评估了它的参数.它还解释了这两者之间的差异
dd <- data.frame(bb=20)
xx <- as.name("bb")
eval(bb, dd)
# Error in eval(bb, dd) : object 'bb' not found
eval(xx, dd)
# [1] 20
Run Code Online (Sandbox Code Playgroud)
在第一次eval()调用中,R无法bb在当前环境中进行评估,因此您会收到错误.但请注意
evalq(bb, dd)
Run Code Online (Sandbox Code Playgroud)
确实有效,因为evalq不会尝试评估第一个表达式参数.