Intercambia dos variables en Elisp


20

Supongamos que tengo

(setq a 1 b 2)

¿Cómo puedo intercambiar elegantemente los valores de ay bsin usar una variable temporal?


Si bien recuerdo la operación de intercambio de ejemplos de programación hace muchos años, no creo que alguna vez haya necesitado una operación de "intercambio". Entonces, ¿dónde encuentras que necesitas tal cosa?
Stefan

@Stefan esta vez, estoy escribiendo una función que toma dos argumentos, y me gustaría asegurarme de que el primer argumento sea el más pequeño de los dos.
PythonNut

1
@PythonNut, bueno, puedes vincular el primer argumento (min a b)y el segundo (max a b). Esta es una solución. Algunos argumentarán que esto requiere dos comparaciones cuando una es suficiente, eso es correcto. Puede manejarlo con una comparación de manera aún más funcional, por ejemplo, utilizando el enlace de desestructuración (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). Esta es otra forma.
Mark Karpov

1
@ Mark es cierto, pero, al menos para mí, eso se siente como aplastar moscas con granadas de mano. cl-destructuring-bindes una herramienta ridículamente poderosa para este trabajo.
PythonNut

Respuestas:


18

Si la memoria me sirve bien y estás dispuesto a usarla, cl-libentonces:

(cl-rotatef a b)

Tenga en cuenta que esta es una forma común de resolver el problema.


20

Este es el idioma elegante que uso ;-).

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

1
Oye, eso está bien. Lo tendré en cuenta si el rendimiento es una preocupación.
PythonNut

1
Ingenioso y sencillo.
Nombre

1
Oh, no es original conmigo, de ninguna manera. Pero es probablemente el uso principal que hago prog1.
Dibujó

1
Eso es más o menos a lo que se cl-rotatefexpande la macro.
abo-abo

6

Si son enteros:

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

:)


2
Para completar, también debe incluir el siguiente clásico: a = a + b, b = a - b, a = a - b. Traducido a Emacs Lisp, por supuesto :-D
Mark Karpov

1
Es cierto, y para completar, señalaré que en asm o C, The XOR Trick funciona para cualquier cosa; registros, memoria, ints, flotantes, estructuras, cadenas (longitud igual) ... En Lisp creo que solo ints. Para grandes bloques de memoria es bueno no necesitar el buffer temporal.
jtgd

@jtgd: para grandes bloques de memoria, puede hacer el intercambio segmento por segmento, con un pequeño búfer.
Clément
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.