如何评估字符串中包含的Elisp代码?


21

这个问题几乎说明了一切:我有一个字符串,其中包含有效Elisp表达式的源代码,并且我想对其进行评估。

(例如,在Python中,表达式的eval("1 - 2 + 3")计算结果为2。)


2
注意,(calc-eval "1 - 2 + 3")即使这不是有效的elisp ,也更适合您的python示例。如果您还不需要calc软件包,则需要先使用加载它(require 'calc)。(我知道这不能回答您的问题。因此,它被表述为评论。)
Tobias

Answers:


24

评估elisp代码字符串是一个分为两个阶段的过程:您需要使用解析字符串read-from-string,然后使用评估结果Lisp表达式eval

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

现在(my-eval-string "(+ 1 2)")评估为3

编辑:

正如指出的@lunaryornread-from-string 只读取第一个表达式,所以这应该是更好的:

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

编辑2:

为了评估elisp代码的副作用,还可以使用with-temp-buffereval-buffereval-buffer始终返回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之所以不理想,是因为它会弄乱所有与缓冲区相关的调用,例如buffer-file-name,...
Ha-Duong Nguyen

5

君士坦丁的答案还可以。

只是提供一些修改:

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

最后一种形式返回列表(1 2 3 4)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.