13

私は Lisp を勉強していましたが、Lisp プログラミングの経験はありません。私の研究の一部で、以下の例に遭遇しました。

> (cons ‘a ‘(a b))  ----> (A A B)
> (cons ‘(a b) ‘a)  ----> ((A B).A)

(cons 'a '(ab))があると応答が(AAB)になる理由と、少し変更して(ab)の後に'aを置くと、応答が((AB )A)?最初のコード行と 2 番目のコード行の違いは何ですか? これらのコードの背後で何が起こっているのでしょうか?

4

5 に答える 5

18

それらをcons-cellsと考えると非常に理解しやすいです。

要するに、コンスセルは正確に2 つの値で構成されます。これの通常の表記法は、ドットを使用することです。次に例を示します。

(cons 'a 'b) ==> (A . B)

しかし、リストは LISP で頻繁に使用されるため、より適切な表記法はドットを削除することです。リストは、2 番目の要素を新しいコンス セルにし、最後の要素をターミネータ (通常は nil、'()Common Lisp では) で終了させることによって作成されます。したがって、これら 2 つは等しいです。

(cons 'a (cons 'b '())) ==> (A B)
(list 'a 'b) ==> (A B)

セルを(cons 'a 'b)作成し[a,b](list 'a 'b)を作成します[a, [b, nil]]。コンス セルでリストをエンコードするための規則に注意してください。それらは inner で終了しますnil

ここで'a、最後のリストにコンスすると、 を含む新しいコンス セルが作成されます[[a, [b, nil]], a]。これは「適切な」リストではないため、つまり で終わっていないためnil、それを書き出す方法はドット: を使用することです(cons '(a b) 'a) ==> ((a b) . a)

ドットが印刷されていない場合、構造体のリストである必要があります[[a, [b, nil]], [a, nil]]

あなたの例

これを行う(cons 'a '(a b))と、シンボル'aとリストが取得'(a b)され、新しいコンス セルに配置されます。したがって、これは で構成されます[a, [a, [b, nil]]]。これは当然インナーで終わるので、nilドット抜きで書いています。

に関しては(cons '(a b) 'a)、これで が得られます[[a, [b, nil]], a]。これはinner で終了しないnilため、ドット表記が使用されます。

cons を使用して、最後の例を内側の nil で終わらせることはできますか? はい、そうすれば

(cons '(a b) (cons 'a '())) ==> ((A B) A)

そして最後に、

(list '(a b) 'a))

と同等です

(cons (cons (cons 'a (cons 'b '())) (cons 'a '())))
于 2015-04-17T15:40:03.087 に答える
7

この視覚化を参照してください。

CL-USER 7 > (sdraw:sdraw '(A A B))

[*|*]--->[*|*]--->[*|*]--->NIL
 |        |        |
 v        v        v
 A        A        B

CL-USER 8 > (sdraw:sdraw '((A B) . A))

[*|*]--->A
 |
 v
[*|*]--->[*|*]--->NIL
 |        |
 v        v
 A        B

また:

CL-USER 9 > (sdraw:sdraw '(A B))

[*|*]--->[*|*]--->NIL
 |        |
 v        v
 A        B

CL-USER 10 > (sdraw:sdraw (cons 'A '(A B)))

[*|*]--->[*|*]--->[*|*]--->NIL
 |        |        |
 v        v        v
 A        A        B

CL-USER 11 > (sdraw:sdraw (cons '(A B) 'A))

[*|*]--->A
 |
 v
[*|*]--->[*|*]--->NIL
 |        |
 v        v
 A        B
于 2015-04-17T17:22:04.993 に答える
4

Aconsは、2 つの値を含むことができるデータ構造です。例(cons 1 2) ; ==> (1 . 2)。前半はcar、後半はcdrです。Aconsは、のいずれかまたは のlist場合です。したがって 、リストです。cdrnillist(1 . (2 . (3 . ())))

がまたはの場合cons、ドットは省略されます。の外側の括弧も省略されます。このように印刷され、印刷されます。同じ構造ですが、視覚化が異なります。の Aにはこのルールがありません。cdrconsnilcdr(3 . ())(3)(1 . (2 . (3 . ())))(1 2 3)conscar

consread 関数は、リストの場合、ドットと奇妙な例外的な印刷形式で読み取りますcdr。読み取り時には、あたかも のように動作しますcons

と の両方に特別なルールがあるreadprint、 のチェーンであっても、リストの錯覚は完成しconsます。

(cons ‘a ‘(a b))  ----> (A . (A B)) 
(cons ‘(a b) ‘a)  ----> ((A B) . A)

はリストであるため、印刷する場合、最初の要素は 3 つの要素の 1 つcdrのリストです。

于 2015-04-17T19:17:38.877 に答える
3

リスト (abc) は、次の 3 つのコンスセルとして表されます (内部に格納されます) (cons 'a (cons 'b (cons 'c '())。最後のペアの cdr には '() が含まれていることに注意してください。

最後の cdr が '() である一連のコンスセルは、プリンターによってリストとして出力されます。したがって、例は (abc) として出力されます。

見てみましょう: (cons 'a '(a b)).

リスト '(ab) は (cons 'a (cons 'b '()) として表されます。これは、以下を (cons 'a '(a b))生成することを意味します(cons 'a (cons 'a (cons 'b '()))

見てみましょう: (cons '(a b) 'a).

リスト '(ab) は (cons 'a (cons 'b '()) として表されます。これは、 を (cons (cons '(a b) 'a))生成することを意味します(cons (cons 'a (cons 'b '()) 'a)

このシリーズは で終わらないことに注意してください'()。プリンターがドット表記を使用していることを示すため。( ... . 'a)は、値が一連のコンスセルで構成され、最後の cdr に が含まれていることを意味します'a。したがって、値(cons (cons 'a (cons 'b '()) 'a)は として出力され'((a b) . a)ます。

于 2015-04-17T16:09:18.847 に答える