2

現在、「Land of Lisp」を読んでいます。最近のコード サンプルの 1 つで、著者は次のように指定しました。

> (eq 'fooo 'FoOo)
T

シンボルが大文字と小文字を区別しないことを証明します。数ページ後、データモードが正式に導入されました。

しかし、私は次のことを本当に理解していません。eqは関数なので、その名前も大文字と小文字を区別しません。したがって、私はこれを行うことができるはずです:

> (eq 'Eq 'EQ)
T

偉大な。それは期待どおりに機能しました。しかし、これをデータモードのリストに入れるとどうなるでしょうか? 心に留めておいてください、私は自分にとって新しいことを試しているだけです。

> (eq '(Eq) '(EQ))
NIL
> (eq '('Eq) '('EQ))
NIL

うーん。わかった?何故ですか?同じ記号を 2 つのリストに入れると、それらのリストは等しいと見なされると予想していました。

ここで質問: リストの内容が比較されるのではなく、リストの「オブジェクト」自体が比較されるということですか? 私は何が欠けていますか?

4

4 に答える 4

4

記号は大文字と小文字を区別します

> (eq (print (intern "foo")) (print (intern "FOO")))
|foo|   ; printed 
FOO     ; printed
==> NIL ; returned

デフォルトのリーダーは Case-Converting です

(eq (read-from-string "foo") (read-from-string "FOO"))
==> T

ただし、リーダーの大文字と小文字を保持することができます。

(let ((*readtable* (copy-readtable)))
  (setf (readtable-case *readtable*) :preserve)
  (eq (read-from-string "foo") (read-from-string "FOO")))
==> NIL

をご覧ください

EQ はポインタの同一性を比較します

Common Lisp は4 つの等価述語を提供します。必要に応じて適切なものを使用する必要があります。

(equal '(Eq) '(EQ))
==> T
(equal '('Eq) '('EQ))
==> T
于 2013-12-02T03:43:53.913 に答える
2

eq物事がまったく同じであることを比較します。ポインターの等価性を考えてください。これは==Java の場合と同様で、論理的に同等のデータであっても偽物になります。

ここでの解決策equalは、「インテリジェントな」ことを行い、リストの要素を比較するだけのものを使用することです

> (equal '(A) '(a))
T

さらに、シンボルは大文字と小文字を区別します。しかし、デフォルトでは、リーダー (コードを AST に変換するもの) はデフォルトで大文字と小文字を区別しません。のような関数でこの違いに気付くことができますintern

于 2013-12-02T03:47:08.353 に答える
1

Lisp シンボルは大文字と小文字を区別します。Lisp リーダーでさえ、大文字と小文字を区別します。唯一のポイントは、リーダーが記号を読み取るとき、通常は大文字にすることです。ケースが重要であることを読者に伝える最も簡単な方法は、縦線の間に入れることです。

> '|asd|def|ghj|
|asdDEFght|
> '|asd|
|asd|
> '|ASD|
ASD
> 'ASD
ASD
> (eq 'asd '|ASD|)
t
> (eq 'asd '|aSd|)
nil

述語はeq、引数が同じオブジェクトであることをチェックします (ポインタと変数の比較に似ていますC) 。

> (defparameter *x* 1)
> (defparameter *y* 1)
> (eq *x* *y*)
nil

したがって、リストに 1 つの要素を書き込むと作成されます'(asd)REPLそして、2 回目に別のリストを作成すると、これらのリストは実際には異なるオブジェクトになります。

> (defparameter *list1* '('qwe))
> (defparameter *list2* '('qwe))
> (eq *list1* list2*) ;this are 2 different objects
nil
> (setf (first *list1* 'def))
> *list1* ;this list has changed
(DEF)
> *list2* ;and this did not
(QWE)

> (setf *list1* *list2*) ;now they are just different names for one object
> *list1*
(QWE)
> (eq *list1* *list2*)
t

オブジェクトを比較する方法は他にもあります ( eq eql equal equalp =)。ドキュメントを読んで遊んでREPL違いを確認することをお勧めします。

于 2013-12-02T05:24:02.593 に答える