21

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.)

  • 2
    Note, (calc-eval "1 - 2 + 3") fits your python example better even if this is not valid elisp. If you do not yet require the calc package you need to load it before with (require 'calc). (I know that this does not answer your question. Hence it is formulated as comment.) – Tobias Jan 28 '16 at 12:35
24

Evaluating a string of elisp code is a two-stage process: you need to parse the string using read-from-string and then evaluate the resulting Lisp expression with eval.

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

Now (my-eval-string "(+ 1 2)") evaluates to 3.

Edit:

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

Edit 2:

To evaluate elisp code for side effects one could also use with-temp-buffer and eval-buffer (eval-buffer always returns 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 is less than ideal because it will mess up with all buffer-related calls, e.g. buffer-file-name, ... – Ha-Duong Nguyen Nov 3 '17 at 11:19
5

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.