Обміняйте двома змінними в Elisp


20

Припустимо, я маю

(setq a 1 b 2)

Як я можу елегантно поміняти місцями значення aта bбез використання тимчасової змінної?


Хоча я багато років тому пам’ятаю операцію свопу з прикладів програмування, я не думаю, що мені ніколи не потрібна була така операція "підміна". То де ви знайдете, що вам потрібна така річ?
Стефан

@Stefan цього разу я пишу функцію, яка бере два аргументи, і я хотів би переконатися, що перший аргумент є меншим із двох.
PythonNut

1
@PythonNut, добре, ви можете прив'язати перший аргумент до (min a b)другого (max a b). Це одне рішення. Дехто стверджує, що для цього потрібно два порівняння, коли одного достатньо, це правильно. Ви можете впоратися з одним порівнянням більш функціональним способом, наприклад, використовуючи руйнування руйнування (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). Це ще один спосіб.
Марк Карпов

1
@ Марк правда, але, принаймні, мені здається, що це відчуває, як ковзаючі мухи ручними гранатами. cl-destructuring-bindє смішно потужним інструментом для цієї роботи.
PythonNut

Відповіді:


18

Якщо пам'ять слугує мені добре, і ви готові використовувати cl-libїї:

(cl-rotatef a b)

Зауважте, що це звичайний спосіб Lisp для вирішення проблеми.


20

Це елегантна ідіома, яку я використовую ;-).

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

1
Гей, це акуратно. Я буду мати це на увазі, якщо продуктивність коли-небудь турбує.
PythonNut

1
Геніальний і простий.
Ім'я

1
О, це ніяк не оригінально зі мною. Але це, мабуть, головне використання я використовую prog1.
Дрю

1
Це майже те, на що cl-rotatefрозширюється макрос.
Або-Або

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
Марк Карпов

1
Правда, і для повноти я зазначу, що в ASM або C The XOR Trick працює на все, що завгодно; регістри, пам'ять, ints, floats, structs, string (однакової довжини) ... У Lisp я думаю лише про ints. Для великих блоків пам’яті приємно, що не потрібен буфер temp.
jtgd

@jtgd: Для великих блоків пам'яті ви можете робити своп по сегментах з невеликим буфером.
Clément
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.