Tausche zwei Variablen in Elisp


20

Angenommen, ich habe

(setq a 1 b 2)

Wie kann ich die Werte von aund bohne Verwendung einer temporären Variablen elegant austauschen ?


Ich erinnere mich an die Swap-Operation aus Programmierbeispielen vor vielen Jahren, aber ich glaube nicht, dass ich jemals eine solche "Swap" -Operation gebraucht habe. Wo finden Sie, dass Sie so etwas brauchen?
Stefan

@ Stefan dieses Mal schreibe ich eine Funktion, die zwei Argumente nimmt, und ich möchte sicherstellen, dass das erste Argument das kleinere der beiden ist.
PythonNut

1
@PythonNut, nun, Sie können das erste Argument an (min a b)und das zweite an binden (max a b). Dies ist eine Lösung. Einige werden argumentieren, dass dies zwei Vergleiche erfordert, wenn einer ausreicht, das ist richtig. Sie können mit einem Vergleich noch funktionaler umgehen, zum Beispiel mit destrukturierendem Binden (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). Das ist ein anderer Weg.
Mark Karpov

1
@Mark true, aber zumindest für mich fühlt sich das so an, als würde man Fliegen mit Handgranaten schlagen. cl-destructuring-bindist ein lächerlich mächtiges Werkzeug für diesen Job.
PythonNut

Antworten:


18

Wenn das Gedächtnis mir gut tut und Sie bereit sind, es zu verwenden, cl-libdann:

(cl-rotatef a b)

Beachten Sie, dass dies die Common-Lisp-Methode zur Lösung des Problems ist.


20

Das ist die elegante Sprache, die ich benutze ;-).

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

1
Hey, das ist ordentlich. Ich werde es im Hinterkopf behalten, wenn die Leistung jemals ein Problem darstellt.
PythonNut

1
Genial und einfach.
Name

1
Oh, es ist keineswegs originell bei mir. Aber es ist wahrscheinlich der Hauptnutzungszweck, den ich benutze prog1.
Drew

1
Das ist so ziemlich das, worauf sich das cl-rotatefMakro ausdehnt.
abo-abo

6

Wenn es sich um ganze Zahlen handelt:

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

:)


2
Der Vollständigkeit halber sollten Sie auch den folgenden Klassiker einschließen: a = a + b, b = a - b, a = a - b. Übersetzt nach Emacs Lisp natürlich :-D
Mark Karpov

1
Richtig, und der Vollständigkeit halber möchte ich darauf hinweisen, dass in asm oder C der XOR-Trick für alles funktioniert; Register, Speicher, Ints, Floats, Structs, Strings (gleich lang) ... In Lisp denke ich nur Ints. Für große Speicherblöcke ist es schön, den temporären Puffer nicht zu benötigen.
Dienstag,

@jtgd: Bei großen Speicherblöcken können Sie Segment für Segment mit einem kleinen Puffer tauschen.
Clément
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.