13

Land of Lisp (これは、私が今まで読んだ中で最高の技術書の 1 つです) を読んでいて、「連想リスト」に出くわしました。

(defparameter *edges* 
  '((living-room (garden west door) 
                 (attic upstairs ladder))
    (garden (living-room east door)) 
    (attic (living-room downstairs ladder))))

Lisp の連想リストは、Java のマップ (キーと値のバインディング) と同じ概念ですか?

キーの場合living-room、どのようにして複数の値を持つことができますか? 値をリストで囲むのはなぜですか?

'(living-room
   ((garden west door)
    (attic upstairs ladder)))
4

4 に答える 4

13
  1. はい、関連付けリストは、キーと値の関連付けを表現する 1 つの方法です。Common Lisp が提供するその他の構造は、プロパティ リストとハッシュ テーブルです。

  2. 値は実際にはすでにリストに含まれています。alist は基本的にペアのリストであり、各ペアの car がキーで、cdr がそのキーに関連付けられた値です。ASSOC でキー LIVING-ROOM を検索し、結果に CDR を適用すると、次のようになります。

CL-USER> (cdr (assoc 'living-room *edges*))
((庭の西側のドア) (屋根裏部屋のは​​しご))

この背後にある魔法はliving-room、 car が で cdr が 2 つの要素のリストであり、リストがペアから構築される方法により、3 要素のリスト(garden west door)(attic upstairs ladder)見なすこともできるという事実にあります。(living-room (garden west door) (attic upstairs ladder))

通常、連想リストを引用符で囲まれたオブジェクトとして表す場合、次のように、リスト表記で語呂合わせするのではなく、ドット ペアで明示的に要素を表すことがわかります。

(定義パラメータ *edges*
  '((リビングルーム。((庭の西のドア)
                    (屋根裏の二階はしご)))
    (庭 . ((リビング東のドア)))
    (屋根裏 . ((リビングルーム階下のはしご))) ))
于 2010-11-11T13:27:11.613 に答える
6

ASSOC はコンス セルを返すため、キーと値の両方が含まれます。

その理由は、これにより、値 (またはキー) を破壊的に更新することが容易になるからです。

ここで、更新は SETF の背後に隠されています。

CL-USER 11 > (defparameter *edges* 
               (copy-tree
                '((living-room (garden west door) 
                               (attic upstairs ladder))
                  (garden (living-room east door)) 
                  (attic (living-room downstairs ladder)))))
*EDGES*

CL-USER 12 > (assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

CL-USER 13 > (cdr (assoc 'living-room *edges*))
((GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))

CL-USER 14 > (setf (cdr (assoc 'living-room *edges*)) '((garden east door)))
((GARDEN EAST DOOR))

CL-USER 15 > (cdr (assoc 'living-room *edges*))
((GARDEN EAST DOOR))
于 2010-11-11T14:34:12.810 に答える
1

まず、Lispの関連リストはJavaのマップ(Key-Valueバインディング)と同じ概念ですか?

Javaのマップはインターフェースです。アリストは、(リンクされた)リストを使用してキーと値のペアを格納する特定の方法です。Javaには、リストと同じプロパティを持つ組み込みのマップはないと思いますが、作成するのは難しくありません。リストはリストであるため、リストのすべての機能とプロパティは引き続き保持されます。

居間の鍵の場合、どのようにして複数の値を持つことができますか?値をリストで囲まないのはなぜですか。

アリストはLisp構文の一部ではありません。これは単なるリストなので、各要素のCDRに好きなものを入れることができます。この場合、それは別のCONSセルです。 ASSOC各要素のCARを見るだけです。

(assoc 'living-room *edges*)
(LIVING-ROOM (GARDEN WEST DOOR) (ATTIC UPSTAIRS LADDER))
于 2010-11-11T13:34:51.950 に答える
1

関連付けリストは、両方がキーを値に関連付ける限り、概念的にはマップに似ています。

値の意味が変わるため、別のリストで複数の値を囲む必要はありません。私はこの本に精通していませんが、*EDGES*定義されている方法、著者が望んでいるようです

(cdr (assoc 'Foobar *edges*))

Foobarから入手できる場所のリストになります。定義されているように、これは単一または複数の値がある場合に当てはまります。

複数の値がある場合、それらの値を別のリストにネストした場合、それらを使用するときに、そのリストからそれらを選択する必要があります。それはあなたに何も与えないでしょう、そしてそれはそれを単一の値の場合とは違うものにするでしょう。

于 2010-11-11T13:34:54.177 に答える