Як оцінити код Elisp, що міститься в рядку?


21

Питання майже все це говорить: у мене є рядок, що містить вихідний код для дійсного виразу Elisp, і я хотів би його оцінити.

(У Python, наприклад, вираз eval("1 - 2 + 3")оцінюється до 2.)


2
Зауважте, (calc-eval "1 - 2 + 3")краще підходить ваш приклад python, навіть якщо це неправильний elisp. Якщо вам ще не потрібен calcпакет, його потрібно завантажити перед цим (require 'calc). (Я знаю, що це не відповідає на ваше запитання. Отже, це сформульовано як коментар.)
Tobias

Відповіді:


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.

Редагувати:

Як вказував @lunaryorn , він read-from-string читає лише перший вираз , тому це має бути краще:

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

Редагувати 2:

Для оцінки коду elisp за побічними ефектами можна також використовувати with-temp-bufferта eval-buffer( eval-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).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.