将值添加到列表的最后一个索引(LISP)

时间:2013-11-23 05:00:43

标签: list lisp common-lisp

我正在尝试将给定变量x添加到列表L。这两个都是函数ADDV的参数。我到目前为止的代码如下:

(defun addV(L x)
    (cond
        ((eq L nil)     nil)
        ((eq (cdr L) nil) (list(+(car L) x)))
        (+ x (first(last L)))
        (butlast L)
        (append L x) ) )

使用参数

L = '(1 2 3 4)
x =  2

评估语句(+ x (first(last L))))时,其值为4。最终目标应该是 L = '(1 2 3 6)

我不确定我做错了什么。任何帮助将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:2)

您的代码格式错误。重新缩进,我们得到

(defun addV(L x)
    (cond
        ((eq L nil)    
            nil)
        ((eq (cdr L) nil) 
            (list (+ (car L) x)))
        (+ 
            x 
            (first (last L)))
        (butlast
            L)
        (append
            L 
            x) ) )
你现在看到问题吗?

由于(not +)NIL,因此输入COND表单中的相应子句。它的主体形式(x(first (last L)))被评估效果,其中没有效果。然后返回最后一个表单的值。

你明显希望它是什么,是

(defun addV (L x)
    (cond
        ((eq L nil)    
            nil)
        ((eq (cdr L) nil) 
            (list (+ (car L) x)))
        (T
            (append
                (butlast L)
                (list (+ x (first (last L))))))))

巧合的是,第二个条款完全没有必要,可以省略,使其成为

(defun addV (L x)
    (if (not (null L))
      (append (butlast L)
              (list (+ x (first (last L)))))))

答案 1 :(得分:2)

如果您可以破坏性地执行此操作,那么您可以使用incflast

(defun increment-last (list x)
  (prog1 list ; return the list
    (incf (first (last list)) x)))

如果您确实需要制作新列表,则必须走到列表末尾才能到达最后一个元素。当你这样做时,你可以跟踪你已经看过的元素(按相反的顺序),并有效地使用反向顺序列表,使用nreconc为你构建新的列表:

(defun plus-last (list x)
  (do ((list list (rest list))
       (rhead '() (list* (first list) rhead)))
      ((endp (rest list))
       (nreconc rhead (list (+ x (first list)))))))
CL-USER> (plus-last '(1 2 3 4) 2)
(1 2 3 6)

如果你对do语法不太满意,你也可以使用尾递归函数(一些Common Lisp实现可以优化到循环中):

(defun plus-last (list x)
  (labels ((pl (list rhead)
             (if (endp (rest list))
                 (nreconc rhead (list (+ x (first list))))
                 (pl (rest list)
                     (list* (first list) rhead)))))
    (pl list '())))

您也可以使用loop,并清楚地表达逻辑:

(defun plus-last (list x)
  (loop for (a . b) on list       
     if (null b) collect (+ a x)
     else collect a))

这也可以通过maplist

完成
(defun plus-last (list x)
  (maplist (lambda (list)
             (if (endp (rest list))
                 (+ x (first list))
                 (first list)))
           list))