Làm thế nào để đánh giá mã Elisp chứa trong một chuỗi?


21

Câu hỏi khá nhiều nói lên tất cả: Tôi có một chuỗi chứa mã nguồn cho biểu thức Elisp hợp lệ và tôi muốn đánh giá nó.

(Ví dụ, trong Python, biểu thức eval("1 - 2 + 3")ước tính là 2.)


2
Lưu ý, (calc-eval "1 - 2 + 3")phù hợp với ví dụ python của bạn tốt hơn ngay cả khi điều này không hợp lệ. Nếu bạn chưa yêu cầu calcgói bạn cần tải trước đó (require 'calc). (Tôi biết rằng điều này không trả lời câu hỏi của bạn. Do đó, nó được coi là bình luận.)
Tobias

Câu trả lời:


24

Đánh giá một chuỗi mã elisp là một quá trình gồm hai giai đoạn: bạn cần phân tích chuỗi bằng cách sử dụng read-from-stringvà sau đó đánh giá biểu thức Lisp kết quả với eval.

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

Bây giờ (my-eval-string "(+ 1 2)")đánh giá để 3.

Chỉnh sửa:

Như @lunaryorn đã chỉ ra , chỉ read-from-string đọc biểu thức đầu tiên , vì vậy điều này sẽ tốt hơn:

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

Chỉnh sửa 2:

Để đánh giá mã elisp cho các tác dụng phụ, người ta cũng có thể sử dụng with-temp-buffereval-buffer( eval-bufferluôn trả về 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ít hơn lý tưởng bởi vì nó sẽ gây rối với tất cả các cuộc gọi liên quan đến bộ đệm, ví dụ: buffer-file-name...
Ha-Duong Nguyen

5

Câu trả lời của Constantine là ổn.

Chỉ để cung cấp một sửa đổi nhỏ:

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

Mẫu cuối cùng trả về danh sách (1 2 3 4).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.