Tukar dua variabel di Elisp

20

Misalkan saya punya

(setq a 1 b 2)

Bagaimana saya bisa secara elegan menukar nilai adan btanpa menggunakan variabel sementara?

PythonNut
sumber
Sementara saya ingat operasi swap dari contoh pemrograman bertahun-tahun yang lalu, saya tidak berpikir saya pernah membutuhkan operasi "swap" seperti itu. Jadi di mana Anda menemukan bahwa Anda membutuhkan hal seperti itu?
Stefan
@Stefan kali ini, saya sedang menulis sebuah fungsi yang membutuhkan dua argumen, dan saya ingin memastikan bahwa argumen pertama adalah yang lebih kecil dari keduanya.
PythonNut
1
@PythonNut, Anda bisa mengikat argumen pertama (min a b)dan kedua (max a b). Ini adalah salah satu solusinya. Beberapa akan berpendapat bahwa ini membutuhkan dua perbandingan ketika satu sudah cukup, itu benar. Anda dapat mengatasinya dengan satu perbandingan dengan fungsi yang lebih fungsional, misalnya menggunakan bilah penataan (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). Ini cara lain.
Mark Karpov
1
@Ark benar, tapi, setidaknya bagiku, rasanya seperti memukul lalat dengan granat tangan. cl-destructuring-bindadalah alat yang sangat kuat untuk pekerjaan ini.
PythonNut

Jawaban:

18

Jika ingatan saya baik dan Anda bersedia menggunakannya, cl-libmaka:

(cl-rotatef a b)

Perhatikan bahwa ini adalah cara umum penyelesaian masalah.

Mark Karpov
sumber
20

Ini adalah ungkapan elegan yang saya gunakan ;-).

(setq a  (prog1 b (setq b  a)))
Drew
sumber
1
Hei, itu rapi. Saya akan mengingatnya jika kinerja selalu menjadi perhatian.
PythonNut
1
Cerdik dan sederhana.
Sebutkan
1
Oh, tidak asli dengan saya, dengan cara apa pun. Tapi mungkin ini adalah kegunaan utama yang saya buat prog1.
Drew
1
Cukup banyak cl-rotatefmakro berkembang.
abo-abo
6

Jika bilangan bulat:

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

:)

jtgd
sumber
2
Untuk kelengkapan Anda juga harus memasukkan klasik berikut: a = a + b, b = a - b, a = a - b. Diterjemahkan ke Emacs Lisp, tentu saja :-D
Mark Karpov
1
Benar, dan untuk kelengkapan saya akan menunjukkan bahwa dalam asm atau C The XOR Trick bekerja untuk apa pun; register, memori, int, mengapung, struct, string (panjang yang sama) ... Dalam Lisp saya pikir hanya ints. Untuk blok memori yang besar, senang tidak perlu buffer temp.
jtgd
@ jtgd: Untuk blok memori yang besar, Anda dapat melakukan swap segment-by-segment, dengan buffer kecil.
Clément