Valuta l’espressione data come stringa

Sono curioso di sapere se R può usare la sua eval() per eseguire calcoli forniti ad esempio da una stringa.

Questo è un caso comune:

 eval("5+5") 

Tuttavia, invece di 10 ottengo:

 [1] "5+5" 

Qualche soluzione?

La eval() valuta un’espressione, ma "5+5" è una stringa, non un’espressione. Usa parse() con text= per cambiare la stringa in un’espressione:

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

Chiamare eval() richiama molti comportamenti, alcuni non sono immediatamente ovvi:

 > 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 

Vedi anche tryCatch .

È ansible utilizzare la funzione parse() per convertire i caratteri in un’espressione. È necessario specificare che l’input sia di testo, perché l’analisi prevede un file per impostazione predefinita:

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

Scusate ma non capisco perché troppe persone credano che una stringa sia qualcosa che potrebbe essere valutata. Devi cambiare la tua mentalità, davvero. Dimentica tutte le connessioni tra stringhe su un lato e le espressioni, le chiamate, la valutazione sull’altro lato.

La (possibilmente) unica connessione è via parse(text = ....) e tutti i bravi programmatori R dovrebbero sapere che questo è raramente un mezzo efficiente o sicuro per build espressioni (o chiamate). Piuttosto, impara di più su substitute() , quote() e possibilmente il potere di usare 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) 

Dic.2017: Ok, ecco un esempio (nei commenti, non c’è una bella formattazione):

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

e se acquisisci più esperienza imparerai che q5 è una "call" mentre e5 è una "expression" , e anche che e5[[1]] è identico a q5 :

 identical(q5, e5[[1]]) # [1] TRUE 

In alternativa, puoi utilizzare le evals dal mio pacchetto evals per acquisire l’output e tutti gli avvisi, gli errori e altri messaggi insieme ai risultati non evals :

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

Al giorno d’oggi puoi anche usare la funzione lazyeval dal pacchetto lazyeval .

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