Мне любопытно узнать, может ли R использовать свою функцию eval()
для выполнения вычислений, предоставленных, например. строка.
Это обычный случай:
eval("5+5")
Однако вместо 10 я получаю:
[1] "5+5"
Любое решение?
Мне любопытно узнать, может ли R использовать свою функцию eval()
для выполнения вычислений, предоставленных, например. строка.
Это обычный случай:
eval("5+5")
Однако вместо 10 я получаю:
[1] "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"
В настоящее время вы также можете использовать функцию lazy_eval
из пакета lazyeval
.
> lazyeval::lazy_eval("5+5")
[1] 10
Аналогично, используя rlang
:
eval(parse_expr("5+5"))