Вычислить выражение, заданное в виде строки
мне любопытно узнать, может ли R использовать его eval()
функция для выполнения вычислений, предоставляемых, например, строкой.
это обычный случай:
eval("5+5")
однако вместо 10 я получаю:
[1] "5+5"
любое решение?
5 ответов
на eval()
функция оценивает выражение, но "5+5"
- это строка, а не выражение. Использовать parse()
С 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.
можно использовать parse()
функции для преобразования символов в выражении. Вам нужно указать, что ввод является текстом, потому что parse ожидает файл по умолчанию:
eval(parse(text="5+5"))
Извините, но я не понимаю, почему слишком много людей даже думают, что строка была чем-то, что можно оценить. Вы должны изменить свое мышление. Забудьте все связи между строками с одной стороны и выражениями, вызовами, оценкой с другой стороны.
(возможно) только соединение через parse(text = ....)
и все хорошие программисты R должны знать, что это редко эффективное или безопасное средство для построения выражений (или вызовов). Скорее узнайте больше о substitute()
, quote()
, и возможно, сила использования 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: Хорошо, вот пример (в комментариях нет хорошего форматирования):
q5 <- quote(5+5)
str(q5)
# language 5 + 5
e5 <- expression(5+5)
str(e5)
# expression(5 + 5)
и если вы получите больше опыта, вы узнаете, что q5
это "call"
, тогда как e5
это "expression"
, и даже e5[[1]]
идентичен q5
:
identical(q5, e5[[1]])
# [1] TRUE
кроме того, вы можете использовать evals
от меня pander
пакет для захвата вывода и всех предупреждений, ошибок и других сообщений вместе с необработанными результатами:
> 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"