Assuming you want to swap the first and last elements, here is an implementation which does that. It traverses the list three times and copies it twice: it is possible to do much better than this, but not without being reasonably devious (in particular I'm reasonably sure a naive implementation with rotatef
also traverses it three times although it only copies it once as you need an initial copy of the list, since rotatef
is destructive):
(defun swapify (list)
;; swap the first and last elements of list
(if (null (rest list))
list
(cons (first (last list)) ; 1st traversal
(append (butlast (rest list)) ; 2nd and third traversals
(list (first list))))))
And here is the devious implementation which traverses the list exactly once. This relies on tail-call elimination: a version which uses a more straightforward loop is fairly obvious.
(defun swapify (list)
;; return a copy of list with the first and last elements swapped
(if (null (rest list))
list
(let ((copy (cons nil nil)))
(labels ((walk (current tail)
(if (null (rest tail))
(progn
(setf (first copy) (first tail)
(rest current) (cons (first list) nil))
copy)
(progn
(setf (rest current) (cons (first tail) nil))
(walk (rest current) (rest tail))))))
(walk copy (rest list))))))