Zamień dwie zmienne w Elisp

20

Załóżmy, że mam

(setq a 1 b 2)

Jak mogę elegancko zamienić wartości ai bbez użycia zmiennej tymczasowej?

PythonNut
źródło
Chociaż pamiętam operację wymiany z przykładów programowania sprzed wielu lat, nie sądzę, żebym kiedykolwiek potrzebował takiej operacji wymiany. Gdzie więc potrzebujesz czegoś takiego?
Stefan
@ Stefan tym razem piszę funkcję, która przyjmuje dwa argumenty i chciałbym upewnić się, że pierwszy argument jest mniejszy z dwóch.
PythonNut,
1
@PythonNut, możesz powiązać pierwszy argument z (min a b)drugim (max a b). To jest jedno rozwiązanie. Niektórzy twierdzą, że wymaga to dwóch porównań, gdy jedno wystarczy, to prawda. Możesz sobie z tym poradzić za pomocą jednego porównania w bardziej funkcjonalny sposób, na przykład używając wiązania restrukturyzacji (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). To jest inny sposób.
Mark Karpov,
1
@Zaznacz prawdę, ale przynajmniej dla mnie wydaje się, że to obrzucanie granatów ręcznych. cl-destructuring-bindjest absurdalnie potężnym narzędziem do tego zadania.
PythonNut,

Odpowiedzi:

18

Jeśli pamięć dobrze mi służy i chcesz ją wykorzystać, cl-libto:

(cl-rotatef a b)

Zauważ, że jest to wspólny sposób rozwiązania problemu.

Mark Karpov
źródło
20

To elegancki idiom, którego używam ;-).

(setq a  (prog1 b (setq b  a)))
Rysował
źródło
1
Hej, to fajnie. Będę o tym pamiętać, jeśli wydajność będzie kiedykolwiek stanowić problem.
PythonNut,
1
Pomysłowy i prosty.
Nazwisko
1
Och, w żadnym wypadku nie jest to ze mną oryginalne. Ale to chyba główny cel, z którego korzystam prog1.
Drew,
1
To właśnie do tego cl-rotatefmakro się rozwija.
abo-abo
6

Jeśli to liczby całkowite:

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

:)

jtgd
źródło
2
Dla kompletności powinieneś również uwzględnić następujący klasyk: a = a + b, b = a - b, a = a - b. Przetłumaczone na Emacsa Lispa, oczywiście :-D
Mark Karpov
1
To prawda i dla kompletności zaznaczę, że w asm lub C Trik XOR działa na wszystko; rejestry, pamięć, liczby całkowite, zmiennoprzecinkowe, struktury, ciągi znaków (równa długość) ... W Lisp myślę tylko o liczbach całkowitych. W przypadku dużych bloków pamięci miło jest nie potrzebować bufora tymczasowego.
jtgd
@jtgd: W przypadku dużych bloków pamięci można wykonywać zamianę segment po segmencie za pomocą małego bufora.
Clément