1. ホーム
  2. functional-programming

[解決済み] Schemeのeq, eqv, equal, =の違いは何ですか?

2023-02-10 09:03:53

質問

Schemeではこれらの演算はどう違うのでしょうか。Stack Overflowで同じような質問を見かけましたが、Lispに関するもので、これらの3つの演算子の比較はされていません。

Schemeで異なる種類のコマンドを書いているのですが、以下のような出力が得られます。

(eq? 5 5) -->#t
(eq? 2.5 2.5) -->#f
(equal? 2.5 2.5) --> #t
(= 2.5 2.5) --> #t

なぜこのようなことが起こるのでしょうか?

どのように解決するのですか?

この質問には、段階的にお答えします。まずは = の同値述語から始めましょう。この述語は = 述語は、2つの数字が等しいかどうかをチェックするために使われます。もし、数値以外のものを与えた場合は、エラーを発生します。

(= 2 3)     => #f
(= 2.5 2.5) => #t
(= '() '()) => error

eq? 述語は、その2つのパラメータがメモリ上で同じオブジェクトを 表しているかどうかをチェックするために使われます。例えば

(define x '(2 3))
(define y '(2 3))
(eq? x y)         => #f
(define y x)
(eq? x y)         => #t

しかし、空のリストが一つしかないことに注意してください。 '() へのポインタが存在します。 0 へのポインターは空リストとみなされます)。従って、空リストを比較する場合 eq? は常に #t (を返します(メモリ上で同じオブジェクトを表しているため)。

(define x '())
(define y '())
(eq? x y)      => #t

では、実装に応じて eq? を返したり返さなかったりします。 #t を返すかもしれません。例えば

(eq? 2 2)     => depends upon the implementation
(eq? "a" "a") => depends upon the implementation

ここで eqv? 述語が登場します。この述語は eqv? とは全く同じで eq? の述語と同じですが、常に #t を返します。例えば

(eqv? 2 2)     => #t
(eqv? "a" "a") => depends upon the implementation

したがって eqv? のスーパーセットです。 eq? の上位互換であり、ほとんどの場合 eqv? の代わりに eq? .

最後に equal? の述語になります。この equal? の述語と全く同じです。 eqv? を満たす対応する要素を持つかどうかをテストするために 使うことができるという点を除いて、述語は と全く同じです。 eqv? を満たす対応する要素があるかどうかを調べるのにも使えます。例えば

(define x '(2 3))
(define y '(2 3))
(equal? x y)      => #t
(eqv? x y)        => #f

一般的には

  1. を使用します。 = の述語を使います。
  2. を使う。 eqv? の述語を使います。
  3. を使う。 equal? 述語は、2つのリストやベクトルなどが等価かどうかをテストしたいときに使います。
  4. は使わないでください。 eq? 述語は使わないでください。