Поменяйте местами две переменные в 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)) ...). Это другой способ.
Марк Карпов

1
@ Правда, но, по крайней мере для меня, это похоже на мух с ручными гранатами. 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
Марк Карпов

1
Правда, и для полноты я укажу, что в asm или C трюк XOR работает для всего; регистры, память, целые числа, числа с плавающей запятой, структуры, строки (равной длины) ... В Лиспе я думаю только целые числа. Для больших блоков памяти хорошо не использовать временный буфер.
Jtgd

@jtgd: Для больших блоков памяти вы можете делать поменять сегмент за сегментом с небольшим буфером.
Климент
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.