ผูกค่าหลายค่าโดยตรงจากรายการโดยไม่ผูกรายการเอง


12

เป็นไปได้ไหมที่จะกำหนดค่าส่งคืนหลายค่าให้กับตัวแปรโดยตรงโดยไม่ต้องผ่านตัวแปรชั่วคราวใน Emacs Lisp?

ตัวอย่างเช่นสมมติว่าฉันมีฟังก์ชันที่ส่งคืนรายการสองรายการ:

(defun test-func ()
  (setq a '(a b))
  (setq b '(c d))
  `(,a ,b))

ถ้าฉันต้องการกำหนดค่าส่งคืนแรกให้กับlist-aและค่าส่งคืนที่สองให้list-bฉันสามารถทำได้โดยใช้ตัวแปรชั่วคราวtempเช่น:

(let* ((temp (test-func)) (list-a (car temp)) (list-b (cadr temp)))
  (message-box (prin1-to-string list-a))
  (message-box (prin1-to-string list-b)))

เป็นไปได้ไหมที่จะทำสิ่งนี้ให้ง่ายขึ้น? (ฉันคุ้นเคยกับ Perl และ Python ที่คุณไม่ต้องระบุตัวแปรชั่วคราว)


2
คุณอาจลองใช้cl-destructuring-bindมาโคร คุณตั้งใจจะใช้setqภายในdefunหรือไม่? setqสร้างตัวแปร "พิเศษ" (สามารถเข้าถึงได้ทั่วโลก) สิ่งที่คุณมักจะใส่ไว้นอกฟังก์ชั่น (เพราะมีความหมายเพียงเล็กน้อยในการประกาศตัวแปรเดียวกันมากกว่าหนึ่งครั้งในขณะที่ฟังก์ชั่นตั้งใจจะทำงานมากกว่าหนึ่งครั้ง)
wvxvw

@wvxvw ขอบคุณ! ใช่ฉันลืมที่จะใช้letในฟังก์ชัน .. ผมไม่ได้วางแผนที่จะตั้งค่าตัวแปรใด ๆ ทั่วโลก :)
HåkonHægland

คำตอบ:


8

Common เสียงกระเพื่อมมีสิ่งอำนวยความสะดวกพิเศษ - ค่าหลายค่าและEmacs เสียงกระเพื่อมห้องสมุดความเข้ากันได้ emulates พวกเขาใช้รายการ

ดังนั้นคุณสามารถทำได้

(defun test-fun ()
  (let ((a 1) (b 2))
    (cl-values a b)))

(cl-multiple-value-bind (a b) (test-fun)
  ...)

(โหลดcl-libและใช้cl-คำนำหน้าสำหรับฟังก์ชัน CL ทั้งหมดใน EL)

หมายเหตุ : หากคุณดูคำตอบ SO ที่เชื่อมโยงข้างต้นคุณจะเห็นว่าการเลียนแบบ MV พร้อมรายการคือให้ใส่อย่างอ่อนโยนอ่อน ๆ (ดู @ ความคิดเห็นของ @ Stefan ด้านล่าง)


มีข้อได้เปรียบของการใช้multiple-value-bindแทนcl-multiple-value-bind(เฉพาะส่วนหลังเท่านั้นที่จะมีการบันทึกไว้ในคู่มือgnu.org/software/emacs/manual/html_node/cl/Multiple-Values.html )?
HåkonHægland

3
@ HåkonHæglandพวกเขาเป็นฟังก์ชั่นเหมือนกัน แต่คุณควรใช้หลัง clแพคเกจไม่ได้หมายความว่าจะใช้อีกต่อไป คุณควรใช้cl-libแพคเกจแทนซึ่งกำหนดฟังก์ชั่นที่มีcl-คำนำหน้า ..
Malabarba

1
ฉันไม่แนะนำให้ใช้cl-values: มันเป็นการเลียนแบบ "ความพยายามที่ดีที่สุด" ของ CommonLisp valuesแต่มันไม่เข้ากันได้จริง ๆ เพราะมันคือการส่งคืนรายการ (เช่นมันเป็นการโกหก) และจากประสบการณ์ของผู้คนไม่ช้าก็เร็ว การจัดการสิ่งเหล่านั้นเป็นรายการ (เช่นการทำลายสิ่งที่เป็นนามธรรม): รายการการใช้ที่ดีกว่าอย่างชัดเจน (และหากคุณไม่ชอบpcase-letให้ใช้cl-destructuring-bindมากกว่าcl-multiple-value-bind)
สเตฟาน

4

นอกเหนือจากการcl-libใช้แพ็คเกจความเข้ากันได้วิธีที่แนะนำใน Elisp คือpcase:

(defun test-fun
  (let ((a '(a b))
        (b '(c d)))
    `(,a ,b)))

(defun other-test-fun ()
  (pcase-let ((`(,a ,b) (test-fun)))
    (message "a = %s; b = %s" a b)))

ข้างpcase-letนอกจากนี้ยังมีpcase-dolist, pcase-lambdaและpcaseตัวเอง

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