web-dev-qa-db-fra.com

Evaluer l'expression donnée sous forme de chaîne

Je suis curieux de savoir si R peut utiliser sa fonction eval() pour effectuer les calculs fournis, par exemple. un string.

C'est un cas fréquent:

eval("5+5")

Cependant, au lieu de 10, je reçois:

[1] "5+5"

Toute solution?

252
Federico Giorgi

La fonction eval() évalue une expression, mais "5+5" est une chaîne et non une expression. Utilisez parse() avec text=<string> pour transformer la chaîne en expression:

> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"

L'appel de eval() appelle de nombreux comportements, dont certains ne sont pas immédiatement évidents:

> 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

Voir aussi tryCatch .

377
Harlan

Vous pouvez utiliser la fonction parse() pour convertir les caractères en une expression. Vous devez spécifier que l'entrée est du texte, car parse attend un fichier par défaut:

eval(parse(text="5+5"))
91
Shane

Désolé mais je ne comprends pas pourquoi trop de gens pensent même qu'une chaîne peut être évaluée. Vous devez changer votre mentalité, vraiment. Oubliez toutes les connexions entre les chaînes d'un côté et les expressions, les appels et l'évaluation de l'autre côté.

La (éventuellement) seule connexion se fait via parse(text = ....) et tous les bons programmeurs R doivent savoir qu'il s'agit rarement d'un moyen efficace ou sûr de créer des expressions (ou des appels). En savoir plus sur substitute(), quote(), et éventuellement sur le pouvoir d’utiliser 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, voici un exemple (dans les commentaires, il n'y a pas de formatage Nice):

q5 <- quote(5+5)
str(q5)
# language 5 + 5

e5 <- expression(5+5)
str(e5)
# expression(5 + 5)

et si vous avez plus d'expérience, vous apprendrez que q5 est un "call" alors que e5 est un "expression", et même que e5[[1]] est identique à q5:

identical(q5, e5[[1]])
# [1] TRUE
40
Martin Mächler

Vous pouvez également utiliser evals à partir de mon package pander pour capturer la sortie et tous les avertissements, erreurs et autres messages, ainsi que les résultats bruts:

> 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"
16
daroczig

De nos jours, vous pouvez également utiliser la fonction lazy_eval du package lazyeval.

> lazyeval::lazy_eval("5+5")
[1] 10

De même, en utilisant rlang:

eval(parse_expr("5+5"))
2
c1au61o_HH