Next: , Up: 修改列表


5.6.1 使用setcar替换列表元素

通过setcar改变一个cons cell的car。当对列表使用时,setcar用一个不同的元素替换列表的一个元素。

— Function: setcar cons object

此函数将object作为cons的新car存储起来,替换它原来的car。换句话说,它改变conscar槽使 其指向object。它返回object的值。例如:

          (setq x '(1 2))
               ⇒ (1 2)
          (setcar x 4)
               ⇒ 4
          x
               ⇒ (4 2)

它cons cell是几个列表的共享结构时,向cons中存储一个新的car将改变每个列表的一个元素。下面是一个例子:

     ;; 创建两个部分共享的列表。
     (setq x1 '(a b c))
          ⇒ (a b c)
     (setq x2 (cons 'z (cdr x1)))
          ⇒ (z b c)
     
     ;; 替换共享cons的car。
     (setcar (cdr x1) 'foo)
          ⇒ foo
     x1                           ; 两个列表同时被改变。
          ⇒ (a foo c)
     x2
          ⇒ (z foo c)
     
     ;; 替换非共享cons的car。
     (setcar x1 'baz)
          ⇒ baz
     x1                           ; 只有一个列表被改变。
          ⇒ (baz foo c)
     x2
          ⇒ (z foo c)

下面是两个共享结构的的列表的图解,展示了为何替换b将同时修改它们:

             --- ---        --- ---      --- ---
     x1---> |   |   |----> |   |   |--> |   |   |--> nil
             --- ---        --- ---      --- ---
              |        -->   |            |
              |       |      |            |
               --> a  |       --> b        --> c
                      |
            --- ---   |
     x2--> |   |   |--
            --- ---
             |
             |
              --> z

下面时盒式记法的另一种形式,展示了相同的关系:

     x1:
      --------------       --------------       --------------
     | car   | cdr  |     | car   | cdr  |     | car   | cdr  |
     |   a   |   o------->|   b   |   o------->|   c   |  nil |
     |       |      |  -->|       |      |     |       |      |
      --------------  |    --------------       --------------
                      |
     x2:              |
      --------------  |
     | car   | cdr  | |
     |   z   |   o----
     |       |      |
      --------------