คำถามที่สวยบอกว่ามันทั้งหมด: ฉันมีสตริงที่มีรหัสแหล่งที่มาสำหรับการแสดงออก Elisp ที่ถูกต้องและฉันต้องการที่จะประเมินมัน
(ใน Python ตัวอย่างนิพจน์eval("1 - 2 + 3")
จะประเมินเป็น 2)
คำถามที่สวยบอกว่ามันทั้งหมด: ฉันมีสตริงที่มีรหัสแหล่งที่มาสำหรับการแสดงออก Elisp ที่ถูกต้องและฉันต้องการที่จะประเมินมัน
(ใน Python ตัวอย่างนิพจน์eval("1 - 2 + 3")
จะประเมินเป็น 2)
คำตอบ:
การประเมินสตริงของรหัส Elisp เป็นกระบวนการขั้นตอนที่สอง: คุณจำเป็นต้องแยกสตริงใช้แล้วประเมินผลการแสดงออกชัดด้วยread-from-string
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")
กับตัวอย่างงูหลามของคุณดีกว่าแม้ว่านี่จะไม่ถูกต้อง elisp หากคุณยังไม่จำเป็นต้องใช้แพคเกจที่คุณต้องโหลดมาก่อนด้วยcalc
(require 'calc)
(ฉันรู้ว่านี่ไม่ได้ตอบคำถามของคุณดังนั้นมันจึงถูกกำหนดเป็นความคิดเห็น)