Common Lispのeq
、eql
、equal
およびの違いは何ですか? equalp
それらのいくつかはタイプをチェックし、いくつかはタイプ全体をチェックすることを理解していますが、どれがどれですか? 他のものよりも使いやすいのはいつですか?
3 に答える
Common Lispから: 等価述語
(eq x y)
x
とy
が同じ同一のオブジェクトである場合にのみ真です。述語は、その
eql
引数がeq
である場合、またはそれらが同じ値を持つ同じ型の数値である場合、またはそれらが同じ文字を表す文字オブジェクトである場合に true です。
equal
引数が構造的に類似した (同形の) オブジェクトである場合、述語は真です。大まかな経験則として、2 つのオブジェクトは、それらの印刷された表現が同じである場合にのみ等しいということです。2 つのオブジェクトは
equalp
、それらが等しい場合です。それらが文字であり、char-equal を満たす場合。これは、アルファベットの大文字と小文字の大文字と小文字の特定の属性を無視します。それらが数値であり、型が異なっていても同じ数値である場合。または、すべてのコンポーネントがある場合equalp
。
上でリンクした同じページの例を次に示します。
(eq 'a 'b) is false.
(eq 'a 'a) is true.
(eq 3 3) might be true or false, depending on the implementation.
(eq 3 3.0) is false.
(eq 3.0 3.0) might be true or false, depending on the implementation.
(eq #c(3 -4) #c(3 -4))
might be true or false, depending on the implementation.
(eq #c(3 -4.0) #c(3 -4)) is false.
(eq (cons 'a 'b) (cons 'a 'c)) is false.
(eq (cons 'a 'b) (cons 'a 'b)) is false.
(eq '(a . b) '(a . b)) might be true or false.
(progn (setq x (cons 'a 'b)) (eq x x)) is true.
(progn (setq x '(a . b)) (eq x x)) is true.
(eq #\A #\A) might be true or false, depending on the implementation.
(eq "Foo" "Foo") might be true or false.
(eq "Foo" (copy-seq "Foo")) is false.
(eq "FOO" "foo") is false.
(eql 'a 'b) is false.
(eql 'a 'a) is true.
(eql 3 3) is true.
(eql 3 3.0) is false.
(eql 3.0 3.0) is true.
(eql #c(3 -4) #c(3 -4)) is true.
(eql #c(3 -4.0) #c(3 -4)) is false.
(eql (cons 'a 'b) (cons 'a 'c)) is false.
(eql (cons 'a 'b) (cons 'a 'b)) is false.
(eql '(a . b) '(a . b)) might be true or false.
(progn (setq x (cons 'a 'b)) (eql x x)) is true.
(progn (setq x '(a . b)) (eql x x)) is true.
(eql #\A #\A) is true.
(eql "Foo" "Foo") might be true or false.
(eql "Foo" (copy-seq "Foo")) is false.
(eql "FOO" "foo") is false.
(equal 'a 'b) is false.
(equal 'a 'a) is true.
(equal 3 3) is true.
(equal 3 3.0) is false.
(equal 3.0 3.0) is true.
(equal #c(3 -4) #c(3 -4)) is true.
(equal #c(3 -4.0) #c(3 -4)) is false.
(equal (cons 'a 'b) (cons 'a 'c)) is false.
(equal (cons 'a 'b) (cons 'a 'b)) is true.
(equal '(a . b) '(a . b)) is true.
(progn (setq x (cons 'a 'b)) (equal x x)) is true.
(progn (setq x '(a . b)) (equal x x)) is true.
(equal #\A #\A) is true.
(equal "Foo" "Foo") is true.
(equal "Foo" (copy-seq "Foo")) is true.
(equal "FOO" "foo") is false.
(equalp 'a 'b) is false.
(equalp 'a 'a) is true.
(equalp 3 3) is true.
(equalp 3 3.0) is true.
(equalp 3.0 3.0) is true.
(equalp #c(3 -4) #c(3 -4)) is true.
(equalp #c(3 -4.0) #c(3 -4)) is true.
(equalp (cons 'a 'b) (cons 'a 'c)) is false.
(equalp (cons 'a 'b) (cons 'a 'b)) is true.
(equalp '(a . b) '(a . b)) is true.
(progn (setq x (cons 'a 'b)) (equalp x x)) is true.
(progn (setq x '(a . b)) (equalp x x)) is true.
(equalp #\A #\A) is true.
(equalp "Foo" "Foo") is true.
(equalp "Foo" (copy-seq "Foo")) is true.
(equalp "FOO" "foo") is true.
ここからと先生のスライド
eqは、その引数 (コンピューター メモリの同じチャンクで表される) が同じシンボルであるかどうかをテストします。
例えば:
(eq 'A'B) NIL
(eq 'RAM'RAM) T
(eq (cons 'a 'b) (cons a' b')) ; これは、両方のコンスに対して異なる呼び出しが行われるため、明らかに異なるメモリ チャンクが割り当てられるためです。
eqlはまず、その引数が EQ を満たすかどうかをテストし、そうでない場合は、それらが同じ型と値の数値であるかどうかを確認しようとします。
例えば:
(eql 4 4.0) NIL
(eql 4 4) T
違いに注意してください:
(eq 4.0 4.0) NIL ; 最初の (受け入れられた) 回答で説明されているように、プラットフォームに依存します
(eql 4.0 4.0) T ; 引数の型と値は同じです
一部の実装 (eq 4.0 4.0) では true を返す場合があります。これは、シンボルの場合と同様に、実装がメモリ内に数値と文字のコピーを 1 つだけ保持する必要があるかどうかが標準で指定されていないためです。経験則として、 使用しないでください。自分が何をしているのか本当にわかっていない限り、数字と文字の eq 。
equalは「健全な」比較関数です。経験則として、これは 2 つのオブジェクトが同じに見える (構造的に似ている、または同形である) かどうかを示すものと考えることができます。これはおそらく、一般的な等値のために使用したい演算子です。数字、文字、記号については eql のように動作しますが、リスト (コンス) と文字列については、それらの要素が
例えば:
(等しい 4 4) T
(等しい (+ 2 2) 4) T
ここで違いに注意してください
(eql (cons 'a 'b) (cons 'a 'b)) NIL
(equal (cons 'a 'b) (cons 'a 'b)) T ; equal は通常、同じものを出力するものに当てはまります
equalpは equal に似ていますが、より高度です。数値の比較は型を区別しません。文字と文字列の比較では、大文字と小文字が区別されません。
例えば:
(equalp (cons 'a 'b) (cons 'a 'b)) T ; 等しい
ここで違いに注意してください
equal(4 4.0) NIL
equalp(4 4.0) T ; equalp は数値型を無差別に扱うため