Avalie a expressão dada como uma string
Pergunta
Estou curioso para saber se r pode usar seu eval()
função para executar os cálculos fornecidos por uma sequência.
Este é um caso comum:
eval("5+5")
No entanto, em vez de 10, eu entendo:
[1] "5+5"
Qualquer solução?
Solução
o eval()
função avalia uma expressão, mas "5+5"
é uma corda, não uma expressão. Usar parse()
com text=<string>
Para mudar a string em uma expressão:
> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"
Chamando eval()
Invoca muitos comportamentos, alguns não são imediatamente óbvios:
> 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
Veja também trycatch.
Outras dicas
Você pode usar o parse()
função para converter os caracteres em uma expressão. Você precisa especificar que a entrada é o texto, porque Parse espera um arquivo por padrão:
eval(parse(text="5+5"))
Desculpe, mas não entendo por que muitas pessoas pensam que uma corda era algo que poderia ser avaliado. Você deve mudar sua mentalidade, realmente. Esqueça todas as conexões entre cordas de um lado e expressões, chamadas, avaliação do outro lado.
A (possivelmente) a conexão é via parse(text = ....)
E todos os bons programadores R devem saber que raramente são meios eficientes ou seguros para construir expressões (ou chamadas). Em vez de aprender mais sobre substitute()
, quote()
, e possivelmente o poder de usar 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)
Dez.2017: OK, aqui está um exemplo (em comentários, não há uma boa formatação):
q5 <- quote(5+5)
str(q5)
# language 5 + 5
e5 <- expression(5+5)
str(e5)
# expression(5 + 5)
E se você ficar mais experiente, aprenderá isso q5
é um "call"
enquanto e5
é um "expression"
, e até que e5[[1]]
é idêntico a q5
:
identical(q5, e5[[1]])
# [1] TRUE
Alternativamente, você pode usar evals
do meu pander
Pacote para capturar a saída e todos os avisos, erros e outras mensagens, juntamente com os resultados brutos:
> 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"
Hoje em dia você também pode usar lazy_eval
função de lazyeval
pacote.
> lazyeval::lazy_eval("5+5")
[1] 10
Da mesma forma usando rlang
:
eval(parse_expr("5+5"))