Next: , Previous: Modifying Lists, Up: Modifying Lists


5.6.1 setcarによるリスト要素の変更

コンスセルのcarを変更するには、setcarを使います。 リストに対して使用すると、 setcarはリストの1つの要素を別の要素に置き換えます。

— Function: setcar cons object

この関数は、consの新たなcarとしてobjectを格納し、 以前のcarを置き換える。 いいかえれば、conscarスロットがobjectを指すように変更する。 この関数は値objectを返す。 たとえば、つぎのようになる。

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

コンスセルが複数のリストの共有構造の一部であるときには、 コンスセルに新たなcarを格納すると、 そのような各リストの1つの要素を変更することになります。

     
     ;; 共有部分がある2つのリストを作る
     (setq x1 '(a b c))
          ⇒ (a b c)
     (setq x2 (cons 'z (cdr x1)))
          ⇒ (z b c)
     
     
     ;; 共有部分のcarを置き換える
     (setcar (cdr x1) 'foo)
          ⇒ foo
     
     x1                           ; 両方のリストが変更されている
          ⇒ (a foo c)
     x2
          ⇒ (z foo c)
     
     
     ;; 非共有部分のcarを置き換える
     (setcar x1 'baz)
          ⇒ baz
     
     x1                           ; 1つのリストだけが変更されている
          ⇒ (baz foo c)
     x2
          ⇒ (z foo c)

変数x1x2に入っている共有部分を持つ2つのリストを図示すると つぎのようになります。 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----
     |       |      |
      --------------