我很好奇R是否可以使用它的eval()函数来执行由字符串等提供的计算。

这是一个常见的情况:

eval("5+5")

然而,我得到的不是10:

[1] "5+5"

有解决方案吗?


当前回答

抱歉,但我不明白为什么这么多人甚至认为字符串是可以计算的东西。你必须改变你的心态,真的。 忘掉一边的字符串和另一边的表达式、调用、求值之间的所有连接。

(可能)唯一的连接是通过解析(text = ....),所有优秀的R程序员都应该知道,这很少是一种有效或安全的构造表达式(或调用)的方法。而是更多地了解substitute()、quote(),以及可能使用do的功能。调用(替代 , ......).

fortunes::fortune("answer is parse")
# If the answer is parse() you should usually rethink the question.
#    -- Thomas Lumley
#       R-help (February 2005)

2017年12月:好的,这里有一个例子(在评论中,没有很好的格式):

q5 <- quote(5+5)
str(q5)
# language 5 + 5

e5 <- expression(5+5)
str(e5)
# expression(5 + 5)

如果你有更多的经验,你会知道q5是一个“调用”,而e5是一个“表达式”,甚至e5[[1]]与q5是相同的:

identical(q5, e5[[1]])
# [1] TRUE

其他回答

可以使用parse()函数将字符转换为表达式。你需要指定输入为文本,因为parse默认期望一个文件:

eval(parse(text="5+5"))

eval()函数计算一个表达式,但"5+5"是一个字符串,而不是表达式。使用parse() with text=<string>将字符串更改为表达式:

> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"

调用eval()会调用许多行为,其中一些行为并不明显:

> class(eval(parse(text="5+5")))
[1] "numeric"
> class(eval(parse(text="gray")))
[1] "function"
> class(eval(parse(text="blue")))
Error in eval(expr, envir, enclos) : object 'blue' not found

参见tryCatch。

类似地使用rlang:

eval(parse_expr("5+5"))

或者,你可以使用我的pander包中的eval来捕获输出和所有警告、错误和其他消息以及原始结果:

> pander::evals("5+5")
[[1]]
$src
[1] "5 + 5"

$result
[1] 10

$output
[1] "[1] 10"

$type
[1] "numeric"

$msg
$msg$messages
NULL

$msg$warnings
NULL

$msg$errors
NULL


$stdout
NULL

attr(,"class")
[1] "evals"

不知道为什么没有人提到两个Base R函数专门做这件事:str2lang()和str2expression()。这些是parse()的变体,但似乎返回的表达式更清晰:

eval(str2lang("5+5"))

# > 10
  
eval(str2expression("5+5"))

# > 10

也想反驳那些海报上说的任何试图这样做的人都是错误的。我在R中读取作为文本存储在文件中的表达式,并试图计算它们。这些函数非常适合这个用例。