Evaluate expression given as a string
I'm curious to know if R can use its eval()
function to perform calculations provided by e.g. a string.
This is a common case:
eval("5+5")
However, instead of 10 I get:
[1] "5+5"
Any solution?
Solution 1:
The eval()
function evaluates an expression, but "5+5"
is a string, not an expression. Use parse()
with text=<string>
to change the string into an expression:
> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"
Calling eval()
invokes many behaviours, some are not immediately obvious:
> 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
See also tryCatch.
Solution 2:
You can use the parse()
function to convert the characters into an expression. You need to specify that the input is text, because parse expects a file by default:
eval(parse(text="5+5"))
Solution 3:
Sorry but I don't understand why too many people even think a string was something that could be evaluated. You must change your mindset, really. Forget all connections between strings on one side and expressions, calls, evaluation on the other side.
The (possibly) only connection is via parse(text = ....)
and all good R programmers should know that this is rarely an efficient or safe means to construct expressions (or calls). Rather learn more about substitute()
, quote()
, and possibly the power of using do.call(substitute, ......)
.
fortunes::fortune("answer is parse")
# If the answer is parse() you should usually rethink the question.
# -- Thomas Lumley
# R-help (February 2005)
Dec.2017: Ok, here is an example (in comments, there's no nice formatting):
q5 <- quote(5+5)
str(q5)
# language 5 + 5
e5 <- expression(5+5)
str(e5)
# expression(5 + 5)
and if you get more experienced you'll learn that q5
is a "call"
whereas e5
is an "expression"
, and even that e5[[1]]
is identical to q5
:
identical(q5, e5[[1]])
# [1] TRUE
Solution 4:
Alternatively, you can use evals
from my pander
package to capture output and all warnings, errors and other messages along with the raw results:
> 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"