The question pretty much says it all: I have a string containing the source code for a valid Elisp expression, and I would like to evaluate it.
(In Python, for example, the expression
eval("1 - 2 + 3") evaluates to 2.)
Emacs Stack Exchange is a question and answer site for those using, extending or developing Emacs. It only takes a minute to sign up.Sign up to join this community
(defun my-eval-string (string) "Evaluate elisp code stored in a string." (eval (car (read-from-string string))))
(my-eval-string "(+ 1 2)") evaluates to
As pointed out by @lunaryorn,
read-from-string reads the first expression only, so this should be better:
(defun my-eval-string (string) (eval (car (read-from-string (format "(progn %s)" string)))))
(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!\")")
The answer of Constantine is okay.
Just to provide a slight modification:
(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)")
The last form returns the list
(1 2 3 4).
In my case I wanted to evaluate elisp in a string only if it actually was valid elisp. Otherwise I just wanted the string as-is.
(defun maybe-eval-string (string) "Maybe evaluate elisp in a given STRING." (or (ignore-errors (eval (car (read-from-string (format "(progn %s)" string)))) ) string)) (print (maybe-eval-string "(format \"hello, %s\" \"world\")")) (print (maybe-eval-string "hello, world"))
"hello, world" "hello, world"
Full credit to @Constantine's answer. I just wrapped it in an
ignore-errors but I though it was handy enough function to post as an answer.