Правильно dfan, это не приведет к обмену двумя значениями.
Причина, по которой вы получаете эту ошибку, заключается в следующем:
(progn
((setf tmp a)
(setf a b)
(setf b tmp)))
должно быть так:
(progn
(setf tmp a)
(setf a b)
(setf b tmp))
У первого progn
есть одно s-выражение в теле, и оно рассматривается как применение функции (setf tmp a)
.В Common Lisp я думаю, что только переменные или lambda
формы могут находиться в функциональной позиции приложения.Я могу ошибаться в деталях, но я знаю, что в CL есть ограничения, которых нет в Схеме.Вот почему это недопустимый вызов.
Например, это недопустимо в CL и приводит к той же ошибке:
CL-USER> ((if (< 1 2) #'+ #'*) 2 3)
; in: LAMBDA NIL
; ((IF (< 1 2) #'+ #'*) 2 3)
;
; caught ERROR:
; illegal function call
;
; compilation unit finished
; caught 1 ERROR condition
Вы МОЖЕТЕ написать своп как макрос (ПРЕДУПРЕЖДЕНИЕ: Я нуб из Lisp, это может быть ужасная причина для макроса и плохо написанного!)
(defmacro swap (a b)
(let ((tmp (gensym)))
`(progn
(setf ,tmp ,a)
(setf ,a ,b)
(setf ,b ,tmp))))
Нет!Не делай этого.Используйте rotatef
, как указывает Терье Нордерхауг.