Elisp에서 두 변수 교체


20

내가 가지고 있다고 가정

(setq a 1 b 2)

어떻게 우아의 값을 교환 할 수 ab임시 변수를 사용하지 않고 있습니까?


수년 전에 프로그래밍 예제의 스왑 작업을 기억하지만 그러한 "스왑"작업이 필요하다고 생각하지는 않습니다. 그런 곳이 필요한 곳은 어디입니까?
Stefan

@Stefan 이번에는 두 가지 인수를 취하는 함수를 작성 중이며 첫 번째 인수가 두 인수 중 더 작은 지 확인하고 싶습니다.
PythonNut

1
@PythonNut, 첫 번째 인수를 (min a b)두 번째에 바인딩 할 수 있습니다 (max a b). 이것은 하나의 솔루션입니다. 어떤 사람들은 이것이 충분할 때 두 번의 비교가 필요하다고 주장 할 것입니다. 더 많은 기능적인 방식으로 비교할 수 있습니다 (예 : destructuring bind) (cl-destructuring-bind (a . b) (if (< a b) (cons a b) (cons b a)) ...). 이것은 다른 방법입니다.
Mark Karpov

1
@ 마크 사실이지만, 적어도 나에게는 수류탄으로 날아 다니는 느낌이 듭니다. cl-destructuring-bind이 작업을 위해 엄청나게 강력한 도구입니다.
PythonNut

답변:


18

메모리가 잘 작동하고 기꺼이 사용하려는 cl-lib경우 :

(cl-rotatef a b)

이것이 문제를 해결하는 일반적인 Lisp 방식입니다.


20

이것은 내가 사용하는 우아한 관용구입니다 ;-).

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

1
이봐, 깔끔하다. 성능이 문제가 될 경우 염두에 두어야합니다.
PythonNut

1
독창적이고 단순합니다.
이름

1
어쨌든 그것은 나에게 독창적이지 않습니다. 그러나 아마도 내가하는 주요 용도 일 것입니다 prog1.
Drew

1
그것은 cl-rotatef매크로가 확장되는 것과 거의 같습니다 .
abo-abo

6

정수인 경우 :

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

:)


2
완성도를 높이려면 a = a + b, b = a-b, a = a-b와 같은 클래식도 포함해야합니다. 코스 - D의, 이맥스 리스프에 번역
마크 카르 포프에게

1
사실, 그리고 완전성을 위해 asm 또는 C에서 XOR Trick은 어떤 것이 든 작동합니다. 레지스터, 메모리, 정수, 수레, 구조체, 문자열 (같은 길이) ... Lisp에서는 정수만 생각합니다. 큰 메모리 블록의 경우 임시 버퍼가 필요하지 않습니다.
jtgd

@jtgd : 큰 메모리 블록의 경우 작은 버퍼를 사용하여 세그먼트별로 스왑을 수행 할 수 있습니다.
Clément
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.