จะประเมินโค้ด Elisp ที่มีอยู่ในสตริงได้อย่างไร?


21

คำถามที่สวยบอกว่ามันทั้งหมด: ฉันมีสตริงที่มีรหัสแหล่งที่มาสำหรับการแสดงออก Elisp ที่ถูกต้องและฉันต้องการที่จะประเมินมัน

(ใน Python ตัวอย่างนิพจน์eval("1 - 2 + 3")จะประเมินเป็น 2)


2
หมายเหตุตรง(calc-eval "1 - 2 + 3")กับตัวอย่างงูหลามของคุณดีกว่าแม้ว่านี่จะไม่ถูกต้อง elisp หากคุณยังไม่จำเป็นต้องใช้แพคเกจที่คุณต้องโหลดมาก่อนด้วยcalc (require 'calc)(ฉันรู้ว่านี่ไม่ได้ตอบคำถามของคุณดังนั้นมันจึงถูกกำหนดเป็นความคิดเห็น)
Tobias

คำตอบ:


24

การประเมินสตริงของรหัส Elisp เป็นกระบวนการขั้นตอนที่สอง: คุณจำเป็นต้องแยกสตริงใช้แล้วประเมินผลการแสดงออกชัดด้วยread-from-stringeval

(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 เหงียน

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)รูปแบบสุดท้ายส่งกลับรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.