为什么不能对表达式中的R调用对象进行求值?(子集化与从调用对象中提取)

qed*_*qed 5 expression r object

我试图了解R expression对象,但遇到了一些困难.

代码段:

a = 1
b = 2
x = expression(sin(a+b+1))
print(class(x[[1]][2]))
eval(x[[1]][2])
Run Code Online (Sandbox Code Playgroud)

结果:

#////////////////////////////////////////////////////
x = expression(sin(a+b+1))
#////////////////////////////////////////////////////
print(class(x[[1]][2]))
[1] "call"
#////////////////////////////////////////////////////
x = expression(sin(a+b+1))
#////////////////////////////////////////////////////
print(class(x[[1]][2]))
[1] "call"
#////////////////////////////////////////////////////
eval(x[[1]][2])
Error in eval(expr, envir, enclos) : attempt to apply non-function
2: eval(expr, envir, enclos)
1: eval(x[[1]][2])
Run Code Online (Sandbox Code Playgroud)

x[[1]][2]是一个call对象,但为什么不能评估它?

gag*_*ews 11

你应该使用[[运营商,而不是[.

a <- 1
b <- 2
eval(x[[1]][[2]])
## [1] 4
Run Code Online (Sandbox Code Playgroud)

这是因为您想要从语言对象中提取信息,而不是将其子集化(查看第二个元素,而不是返回由第二个元素组成的子序列).

换句话说,子集a call给你一个call:

x[[1]][2]
## (a + b + 1)()
Run Code Online (Sandbox Code Playgroud)

并且因为没有这样的函数a+b+1(实际上,a+b+1评估的结果不是函数对象),R会抛出错误.

有趣的是,如果+返回一个函数对象,这可能有意义:

"+" <- function(a, b) { function() print(":-)") }
(a+b+1)()
[1] ":-)"
Run Code Online (Sandbox Code Playgroud)

另一方面,从调用对象中提取元素会为您提供一个可以计算的表达式:

x[[1]][[2]]
a + b + 1
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,这个表达式也是一个电话,这里相当于"+"(a, "+"(b, 1)).

编辑.更正式地说,调用是表单的一个表达式(序列):

(f, a1, ..., an),
Run Code Online (Sandbox Code Playgroud)

我们通常读作:

f(a1, ..., an).
Run Code Online (Sandbox Code Playgroud)

因此,序列的第一个元素是用于转换其他元素以获得输出值的对象.

x[[1]]相当于:

(sin, a+b+1)
Run Code Online (Sandbox Code Playgroud)

或者,更详细地说,

(sin, (+, a, (+, b, 1))).
Run Code Online (Sandbox Code Playgroud)

因此,x[[1]][2]采用上面仅由第二个元素组成的子序列并返回:

((+, a, (+, b, 1)))
Run Code Online (Sandbox Code Playgroud)

(即(a+b+1)()- 没有args!).另一方面,x[[1]][[2]]提取(查看内部)第二个元素并给出:

(+,a,(+,b,1)),

a+b+1(注意少一对括号).

EDIT2:所有这些都体现了R语言的美感和表现力,至少恕我直言.让我们研究另一个我们创建一个调用的例子f1(f2(f3, f4), f3, f4),它可以用一个序列来表示

(f1, (f2, f3, f4), f3, f4).
Run Code Online (Sandbox Code Playgroud)

我们有:

f <- function(...) invisible(NULL)
f1 <- f; f2 <- f; f3 <- f; f4 <- f # for sake of clarity below
expr <- quote(f1(f2(f3, f4), f3, f4))
print(expr)
## f1(f2(f3, f4), f3, f4),           i.e. (f1, (f2, f3, f4), f3, f4)
print(expr[1:3])
## f1(f2(f3, f4), f3),               i.e. (f1, (f2, f3, f4), f3)
print(expr[3:4])
## f3(f4),                           i.e. (f3, f4)
print(expr[3])
## f3(),                             i.e. (f3)
expr[2]
## f2(f3, f4)(),                     i.e. ((f2, f3, f4)) [subsetting!]
Run Code Online (Sandbox Code Playgroud)

而现在完全不同的东西:

expr[[2]]
## f2(f3, f4),                       i.e. (f2, f3, f4) [extraction]
Run Code Online (Sandbox Code Playgroud)

希望这能澄清这些问题.

  • 一个给你调用`(a + b + 1)()`,另一个调用``+'(a,"+"(b,1))`. (3认同)
  • 哦,我想给你10个赞成票!这本书是免费提供的吗? (2认同)