what is to append as push is to cons, in Lisp?

前端 未结 5 1355
太阳男子
太阳男子 2020-12-11 03:15
(push x list)

expands to

(setq list (cons x list))

What expands to the following:

(setq list (app         


        
5条回答
  •  半阙折子戏
    2020-12-11 03:42

    To clarify things a bit, about Vatine's answer:

    With the initial question, we have

    (defparameter list '(1 2 3))
    (defparameter list2 '(4 5 6))
    (setq list (append list2 list))
    
    list
    (4 5 6 1 2 3)
    
    list2
    (4 5 6)
    

    That is, list2 is prepended to list, but list2 is not itself modified. The reason is simply that append does not change directly its arguments.

    Now, with

    (defmacro tail-push (place val)
      (let ((tmp (gensym "TAIL")))
        `(let ((,tmp ,place))
            (setf (cdr (last ,tmp)) ,val)
            ,tmp)))
    

    First try

    (defparameter list '(1 2 3))
    (defparameter list2 '(4 5 6))
    (tail-push list2 list)
    
    list
    (1 2 3)
    
    list2
    (4 5 6 1 2 3)
    

    Second try, switching the arguments

    (defparameter list '(1 2 3))
    (defparameter list2 '(4 5 6))
    (tail-push list list2)
    
    list
    (1 2 3 4 5 6)
    
    list2
    (4 5 6)
    

    Either way, one of the list is appended to the other, simply because nconc, or (rplacd (last ...) ...) or here, directly (setf (cdr (last ...)) ...), can only append, not prepend. And we can't just claim that the first try gives the right answer '(4 5 6 1 2 3), because list was not modified, whereas list2 was, which is absolutely not what was required.

    However, with Joshua's solution,

    (defun swapped-append (tail head)
      (append head tail))
    
    (define-modify-macro swapped-appendf (&rest args)
      swapped-append)
    
    (defparameter list '(1 2 3))
    (defparameter list2 '(4 5 6))
    (swapped-appendf list list2)
    
    list
    (4 5 6 1 2 3)
    
    list2
    (4 5 6)
    

    And it's working as expected.

提交回复
热议问题