Вычислить выражение, заданное в виде строки

мне любопытно узнать, может ли 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"

В настоящее время вы также можете использовать