สลับสองตัวแปรใน Elisp


20

สมมติว่าฉันมี

(setq a 1 b 2)

ฉันจะสลับค่าของaและbโดยไม่ใช้ตัวแปรชั่วคราวได้อย่างไร


ในขณะที่ฉันจำการดำเนินการสลับจากตัวอย่างการเขียนโปรแกรมเมื่อหลายปีก่อนฉันไม่คิดว่าฉันต้องการการดำเนินการ "สลับ" เช่นนี้มาก่อน ดังนั้นคุณจะพบสิ่งที่คุณต้องการสิ่งที่?
สเตฟาน

@ สเตฟานในเวลานี้ฉันกำลังเขียนฟังก์ชั่นที่ใช้สองข้อโต้แย้งและฉันต้องการให้แน่ใจว่าอาร์กิวเมนต์แรกมีขนาดเล็กกว่าของทั้งสอง
PythonNut

1
@PythonNut ที่ดีที่คุณสามารถผูกอาร์กิวเมนต์แรกและครั้งที่สองไป(min a b) (max a b)นี่คือทางออกหนึ่ง บางคนอาจแย้งว่านี่ต้องใช้การเปรียบเทียบสองแบบเมื่อมีพอเพียง (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...)คุณสามารถจัดการกับมันด้วยการเปรียบเทียบในลักษณะการทำงานมากขึ้นยังคงเป็นเช่นใช้ผูก destructuring นี่เป็นอีกวิธีหนึ่ง
Mark Karpov

1
@ Mark จริง แต่อย่างน้อยสำหรับฉันที่รู้สึกเหมือนแมลงวันตบกับระเบิดมือ cl-destructuring-bindเป็นเครื่องมือที่ทรงพลังสำหรับงานนี้
PythonNut

คำตอบ:


18

หากหน่วยความจำรองรับฉันได้ดีและคุณยินดีที่จะใช้cl-lib:

(cl-rotatef a b)

โปรดทราบว่านี่เป็นวิธี Common LISP ในการแก้ปัญหา


20

นี่คือสำนวนที่สง่างามที่ฉันใช้ ;-)

(setq a  (prog1 b (setq b  a)))

1
เฮ้นั่นเรียบร้อย ฉันจะจำไว้ถ้าการแสดงนั้นเป็นสิ่งที่น่ากังวล
PythonNut

1
แยบยลและเรียบง่าย
ชื่อ

1
โอ้มันไม่ได้เป็นต้นฉบับกับฉันไม่ว่าด้วยวิธีใด prog1แต่มันอาจจะใช้หลักของผมทำ
ดึง

1
นั่นเป็นสิ่งที่cl-rotatefแมโครขยายออกไป
abo-abo

6

หากเป็นจำนวนเต็ม:

(setq a (logxor a b))
(setq b (logxor a b))
(setq a (logxor a b))

:)


2
เพื่อความสมบูรณ์คุณควรรวมคลาสสิกต่อไปนี้: a = a + b, b = a - b, a = a - b แปลเป็น Emacs Lisp แน่นอน :-D
Mark Karpov

1
จริงและเพื่อความสมบูรณ์ฉันจะชี้ให้เห็นว่าใน Asm หรือ C The XOR Trick นั้นใช้ได้ผลกับทุกอย่าง ลงทะเบียน, หน่วยความจำ, ints, ลอย, structs, สตริง (ความยาวเท่ากัน) ... ในเสียงกระเพื่อมฉันคิดว่า ints เท่านั้น สำหรับบล็อกหน่วยความจำขนาดใหญ่เป็นเรื่องดีที่ไม่ต้องการบัฟเฟอร์ชั่วคราว
jtgd

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