Come valutare il codice Elisp contenuto in una stringa?


21

La domanda dice praticamente tutto: ho una stringa contenente il codice sorgente per un'espressione Elisp valida e vorrei valutarla.

(In Python, ad esempio, l'espressione eval("1 - 2 + 3")restituisce 2.)


2
Nota, si (calc-eval "1 - 2 + 3")adatta meglio al tuo esempio di pitone anche se questo non è valido elisp. Se non è ancora necessario il calcpacchetto, è necessario caricarlo prima (require 'calc). (So ​​che questo non risponde alla tua domanda. Quindi è formulato come commento.)
Tobias

Risposte:


24

La valutazione di una stringa di codice elisp è un processo in due fasi: è necessario analizzare la stringa utilizzando read-from-stringe quindi valutare l'espressione Lisp risultante con eval.

(defun my-eval-string (string)
  "Evaluate elisp code stored in a string."
  (eval (car (read-from-string string))))

Ora (my-eval-string "(+ 1 2)")valuta 3.

Modificare:

Come sottolineato da @lunaryorn , read-from-string legge solo la prima espressione , quindi dovrebbe essere migliore:

(defun my-eval-string (string)
  (eval (car (read-from-string (format "(progn %s)" string)))))

Modifica 2:

Per valutare il codice elisp per gli effetti collaterali si potrebbe anche usare with-temp-buffere eval-buffer( eval-bufferritorna sempre nil).

(defun my-eval-string-for-side-effects (string)
  "Evaluate a string of elisp code for side effects."
  (with-temp-buffer
    (insert string)
    (eval-buffer)))

(my-eval-string-for-side-effects "(message \"hello!\")")

with-temp-bufferè tutt'altro che ideale perché confonderà tutte le chiamate relative al buffer, ad esempio buffer-file-name...
Ha-Duong Nguyen,

5

La risposta di Costantino è ok.

Giusto per fornire una leggera modifica:

(defun my-eval-string (str)
  "Read and evaluate all forms in str.
Return the results of all forms as a list."
  (let ((next 0)
        ret)
    (condition-case err
        (while t
          (setq ret (cons (funcall (lambda (ret)
                                     (setq next (cdr ret))
                                     (eval (car ret)))
                                   (read-from-string str next))
                          ret)))
      (end-of-file))
    (nreverse ret)))

(my-eval-string "1 2 3 (+ 3 1)")

L'ultimo modulo restituisce l'elenco (1 2 3 4).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.