lisp交换列表元素

时间:2017-03-06 15:55:30

标签: lisp common-lisp

这是我的lisp代码。

(defun f (lst)
                (append (subst (last lst) (first lst) (car lst))
                (subst (first lst) (last lst) (cdr lst)))
                )

(f'(a b c d))

此代码的输出为(D B C.A)

该功能运行良好,但因符号而无法完成。 我想要没有符号的make(D B C A)。

我该如何解决?或者有更好的方法吗?

我很感激帮助。

3 个答案:

答案 0 :(得分:2)

假设您有意做某事like this,您可以try using rotatef

? (setf lst '(a b c d))
(A B C D)
? lst
(A B C D)
? (rotatef (nth 0 lst) (nth (- (length lst) 1) lst))
;Compiler warnings :
;   In an anonymous lambda form at position 0: Undeclared free variable LST (3 references)
NIL
? lst
(D B C A)

答案 1 :(得分:1)

假设您要交换第一个和最后一个元素,这里有一个实现。它遍历列表三次并复制两次:它可能做得比这更好,但并非没有合理的狡猾(特别是我有理由相信rotatef的一个天真的实现也遍历了三次虽然它只复制一次,因为你需要列表的初始副本,因为rotatef具有破坏性):

(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))))))

这是一个狡猾的实现,它只遍历列表一次。这依赖于尾部调用消除:使用更简单循环的版本是相当明显的。

(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))))))

答案 2 :(得分:0)

符号是因为您将列表附加到元素,如果您使用相同代码将元素转换为列表:(list (car lst)) 它将不再有符号。