ここでは、2つのオブジェクトの等価性を判定する関数について説明します。その他の関数は、文字列などの特定の型のオブジェクト間における内容の等価性を判定します。これらの述語については、該当するデータ型を解説している章を参照してください。
この関数は、object1 と object2
が同一のオブジェクトであれば t を、そうでなければ nil を返します。
object1 と object2
が同じ名前のシンボルである場合、通常は同一のオブジェクトとなります—ただし、例外については シンボルの作成とインターニング
を参照してください。その他の非数値型(例:リスト、ベクトル、文字列)では、内容や要素が同一である2つの引数が必ずしも互いに eq であるとは限りません。これらが eq
となるのは、それらが同一のオブジェクトである場合、すなわち一方の内容の変更がもう一方の内容の同様の変更に反映される場合に限られます。
object1 と object2
が型や値の異なる数値である場合、それらは同一のオブジェクトとはなり得ず、eq は nil を返します。これらが同じ値を持つ fixnum である場合、それらは同一のオブジェクトとなり、eq は t
を返します。個別に計算されたものの、たまたま同じ値を持ち、かつ同じ非 fixnum
数値型である場合、それらが同一のオブジェクトであるとは限りません。eq は、Lisp
インタプリタが1つのオブジェクトを作成したか2つのオブジェクトを作成したかに応じて、t または
nil を返します。
object1 または object2
が位置を持つ記号である場合、symbols-with-pos-enabled が nil 以外であれば、eq
はそれを単なる記号として扱います(位置を持つ記号 を参照)。
(eq 'abc 'abc) ⇒ t (eq 'abc 'ABC) ⇒ nil (eq ?A ?A) ⇒ t (eq 3 3) ⇒ t
等しい非fixnum数は、同一のオブジェクトである場合もあれば、そうでない場合もあります:
(eq 3.0 3.0) ⇒ t or nil (eq (expt 10 50) (expt 10 50)) ⇒ t or nil
新たに作成された可変オブジェクトは個別のものです:
(eq (list 1 2 3) (list 1 2 3)) ⇒ nil (eq (point-marker) (point-marker)) ⇒ nil
他の型の等しい定数は、同一のオブジェクトである場合もあれば、そうでない場合もある:
(eq "abc" "abc") ⇒ t or nil (eq '(1 2 3) '(1 2 3)) ⇒ t or nil (eq [1 2 3] [1 2 3]) ⇒ t or nil
同一のリテラル定数である場合を除き:
(let ((x "abc")) (eq x x)) ⇒ t (let ((x '(1 2 3))) (eq x x)) ⇒ t (let ((x [1 2 3])) (eq x x)) ⇒ t
make-symbol
関数は、Lisp式で名前を記述した際に使用されるシンボルとは異なる、インターニングされていないシンボルを返します。同じ名前を持つ異なるシンボルは、eq ではありません。シンボルの作成とインターニングを参照してください。
(eq (make-symbol "foo") 'foo)
⇒ nil
Emacs
Lispのバイトコンパイラは、リテラル文字列などの同一のリテラルオブジェクトを同一オブジェクトへの参照に集約することがあります。その結果、バイトコンパイルされたコードではこうしたオブジェクトを
eq
として比較しますが、同じコードのインタプリタ版ではそうなりません。したがって、同一のリテラル内容を持つオブジェクトが eq であるか、あるいは eq
でないかという点にコードが依存してはならず、代わりに後述する equal
のようにオブジェクトの内容を比較する関数を使用する必要があります。同様に、リテラルオブジェクトを変更(例:リテラル文字列にテキストプロパティを付与する)すべきではありません。バイトコンパイラがそれらを集約した場合、同じ内容を持つ他のリテラルオブジェクトに影響を及ぼす可能性があるためです。
この関数は、object1 と object2
の成分が等しい場合は t を、そうでない場合は nil を返します。eq
が引数が同一のオブジェクトであるかを判定するのに対し、equal
は同一でない引数の内部を確認し、要素や内容が同一であるかを判定します。したがって、2つのオブジェクトが eq であれば equal
となりますが、その逆が必ずしも成り立つとは限りません。
(equal 'foo 'foo)
⇒ t
(equal 456 456)
⇒ t
(equal "asdf" "asdf")
⇒ t
(equal '(1 (2 (3))) '(1 (2 (3))))
⇒ t
(equal [(1 2) 3] [(1 2) 3])
⇒ t
(equal (point-marker) (point-marker))
⇒ t
equal 関数は、文字列と bool-vector を値に基づいて比較します。数値は eql を用いて、型と数値値に基づいて比較されます。リスト、cons
セル、ベクトル、レコード、マーカー、文字テーブル、フォントオブジェクト、および関数オブジェクト(クロージャ)2 は、equal
を用いてその構成要素を再帰的に比較します。
文字列の比較は大文字小文字を区別しますが、テキストプロパティは考慮されず、文字列内の文字のみが比較されます。テキストプロパティを参照してください。テキストプロパティも含めて比較する場合は、equal-including-properties
を使用してください。技術的な理由により、ユニバイト文字列とマルチバイト文字列が equal
となるのは、両者が同じ文字コード列を持ち、かつそれらすべてのコードが 0 から 127 の範囲(ASCII)にある場合に限られます。
(equal "asdf" "ASDF")
⇒ nil
object1 または object2
に位置を持つ記号が含まれている場合、symbols-with-pos-enabled が nil でないとき、equal
はそれらを単なる記号として扱います。それ以外の場合、equal
は位置を持つ2つの記号を、それぞれの構成要素を比較することで比較します。位置を持つ記号 を参照してください。
その他のオブジェクトは、eqである場合にのみequalとみなされます。例えば、2つの異なるバッファは、テキスト内容が同一であっても、決してequalとはみなされません。
equal については、等価性が再帰的に定義されます。例えば、2つのコンスセル x と y があるとき、(equal x y) が t を返すのは、以下の式がいずれも
t を返す場合に限られます:
(equal (car x) (car y)) (equal (cdr x) (cdr y))
したがって、非常に深くネストされたオブジェクトを比較すると、深い再帰が発生し、エラーにつながる可能性があります。
この関数はいかなる場合においても equal
と同様に動作しますが、2つの文字列が等しいためには、それらが同じテキストプロパティを持っている必要があります。
(equal "asdf" (propertize "asdf" 'asdf t))
⇒ t
(equal-including-properties "asdf"
(propertize "asdf" 'asdf t))
⇒ nil