Troque duas variáveis ​​no Elisp

20

Suponha que eu tenha

(setq a 1 b 2)

Como posso trocar elegantemente os valores de ae bsem usar uma variável temporária?

PythonNut
fonte
Embora eu me lembre da operação de troca de exemplos de programação muitos anos atrás, acho que nunca precisei de uma operação de "troca". Então, onde você acha que precisa disso?
Stefan
@ Stefan neste momento, estou escrevendo uma função que recebe dois argumentos, e gostaria de garantir que o primeiro argumento seja o menor dos dois.
precisa saber é o seguinte
1
@ PythonNut, bem, você pode vincular o primeiro argumento (min a b)e o segundo (max a b). Esta é uma solução. Alguns argumentam que isso requer duas comparações quando uma basta, isso mesmo. Você pode lidar com isso com uma comparação ainda mais funcional, por exemplo, usando a ligação de desestruturação (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). Esta é outra maneira.
Mark Karpov
1
@ Mark verdade, mas, pelo menos para mim, parece que voa golpeando com granadas de mão. cl-destructuring-bindé uma ferramenta ridiculamente poderosa para este trabalho.
precisa saber é o seguinte

Respostas:

18

Se a memória me servir bem e você estiver disposto a usar, cl-libentão:

(cl-rotatef a b)

Observe que essa é a maneira Common Lisp de resolver o problema.

Mark Karpov
fonte
20

Este é o idioma elegante que eu uso ;-).

(setq a  (prog1 b (setq b  a)))
Desenhou
fonte
1
Ei, isso é legal. Vou me lembrar disso se o desempenho for uma preocupação.
precisa saber é o seguinte
1
Engenhoso e simples.
Nome
1
Oh, não é original para mim, por qualquer meio. Mas é provavelmente o principal uso que faço prog1.
21415 Drew
1
Isso é basicamente o que a cl-rotatefmacro expande.
abo-abo
6

Se for números inteiros:

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

:)

jtgd
fonte
2
Para completar, você também deve incluir o seguinte clássico: a = a + b, b = a - b, a = a - b. Traduzido para Emacs Lisp, é claro :-D
Mark Karpov
1
É verdade, e para ser completo, vou apontar que, em asm ou C, o The XOR Trick funciona para qualquer coisa; registros, memória, ints, floats, structs, strings (comprimento igual) ... No Lisp, acho que apenas ints. Para grandes blocos de memória, é bom não precisar do buffer temporário.
Jtgd
@ jtgd: Para grandes blocos de memória, você pode fazer a troca segmento por segmento, com um pequeno buffer.
Clément