Відповіді:
Оцінка рядка коду 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
, ...
Відповідь Костянтина гаразд.
Просто, щоб забезпечити незначну модифікацію:
(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)
.
(calc-eval "1 - 2 + 3")
краще підходить ваш приклад python, навіть якщо це неправильний elisp. Якщо вам ще не потрібенcalc
пакет, його потрібно завантажити перед цим(require 'calc)
. (Я знаю, що це не відповідає на ваше запитання. Отже, це сформульовано як коментар.)