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?


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.


20

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

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

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))

:)


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.