ここでは2つのオブジェクトの同一性をテストする関数を説明します。(たとえば文字列などの)特定の型のオブジェクト同士で内容の同一性をテストするには、別の関数を使用します。これらの述語にたいしては、そのデータ型を説明する適切なチャプターを参照してください。
この関数はobject1とobject2が同じオブジェクトならt
、それ以外はnil
をリターンする。
object1とobject2が同じ名前をもつシンボルなら、通常は同じオブジェクトだが例外もある。シンボルの作成とinternを参照のこと。他の非数値型(リストやベクター、文字列などの)にたいしては、同じ内容(または要素)の2つの引数が両者eq
である必要はない。これらが同じオブジェクトの場合だけeq
であり、その場合には一方の内容を変更するともう一方の内容にも同じ変更が反映される。
object1とobject2が異なるタイプや値をもつ数値なら同じオブジェクトではなく、eq
はnil
をリターンする。同じ値をもつfixnumなら同じオブジェクトであり、eq
はt
をリターンする。別個に計算されてたまたま同じ値をもち、かつ非fixnumタイプの同じ数値型なら、それらは同じかもしれないし違うかもしれず、Lispインタープリターが作成したオブジェクトが1つか2つかに依存してeq
はt
かnil
をリターンする。
object1かobject2が位置つきシンボル(symbol with
position)の場合には、symbols-with-pos-enabled
が非nil
ならeq
はそれをbareシンボル(bare
symbol: 裸のシンボル)とみなす(位置つきシンボルを参照)。
(eq 'foo 'foo) ⇒ t
(eq ?A ?A) ⇒ t
(eq 3.0 3.0) ⇒ t または nil ;; 浮動小数にたいするeqではオブジェクト同じかもしれず違うかもしれない
(eq (make-string 3 ?A) (make-string 3 ?A)) ⇒ nil
(eq "asdf" "asdf") ⇒ t または nil ;; 文字列コンテンツにたいするeqではオブジェクト同じかもしれず違うかもしれない
(eq '(1 (2 (3))) '(1 (2 (3)))) ⇒ nil
(setq foo '(1 (2 (3)))) ⇒ (1 (2 (3))) (eq foo foo) ⇒ t (eq foo '(1 (2 (3)))) ⇒ nil
(eq [(1 2) 3] [(1 2) 3]) ⇒ nil
(eq (point-marker) (point-marker)) ⇒ nil
make-symbol
関数はinternされていないシンボルをリターンする。これはLisp式内でその名前を記述したシンボルとは区別される。同じ名前の異なるシンボルはeq
ではない。シンボルの作成とinternを参照のこと。
(eq (make-symbol "foo") 'foo) ⇒ nil
Emacs Lispバイトコンパイラーはリテラル文字列のような等価なリテラルオブジェクトを同一オブジェクトにたいする参照に落し込む(collapse
into)かもしれない。バイトコンパイルされたコードはそのようなオブジェクトをeq
で比較するだろうが、そうでないコードは異なるという効果がある。したがってコードではオブジェクトのリテラルコンテンツがeq
か否かではなく、以下に説明するequal
のような関数でオブジェクトの関数を使用すること。同様にコードではリテラルオブジェクトを変更(たとえばリテラル文字列へのテキストプロパティのput)しないこと。バイトコンパイラーがそれらの落し込みを行っていたら、同一コンテンツをもつ別のリテラルオブジェクトに影響があるかもしれない。
この関数はobject1とobject2が同じ構成要素をもつならt
、それ以外はnil
をリターンする。eq
が引数が同じオブジェクトなのかテストするのにたいして、equal
は同一でない引数の内部を調べて、それらの要素または内容が同一化をテストする。したがって2つのオブジェクトがeq
ならばそれらはequal
だが、その逆は常に真ではない。
(equal 'foo 'foo) ⇒ t
(equal 456 456) ⇒ t
(equal "asdf" "asdf") ⇒ t
(eq "asdf" "asdf") ⇒ nil
(equal '(1 (2 (3))) '(1 (2 (3)))) ⇒ t
(eq '(1 (2 (3))) '(1 (2 (3)))) ⇒ nil
(equal [(1 2) 3] [(1 2) 3]) ⇒ t
(eq [(1 2) 3] [(1 2) 3]) ⇒ nil
(equal (point-marker) (point-marker)) ⇒ t
(eq (point-marker) (point-marker)) ⇒ nil
equal
関数は文字列およびboolベクターを値で比較する。タイプと数値的な値によって数値を比較する場合にはeql
を用いる。リスト、コンスセル、ベクター、文字テーブル、フォントオブジェクト、関数オブジェクト(クロージャ)2
を比較する場合には、equal
を用いてそれぞれを構成する要素を再帰的に比較する。
文字列の比較はcaseを区別するがテキストプロパティは考慮しない — これは文字列内の文字だけを比較する。テキストのプロパティを参照のこと。テキストプロパティも比較する場合には、equal-including-properties
を使用すること。技術的な理由によりユニバイト文字列とマルチバイト文字列は、それらが同じ文字コードのシーケンスを含み、それらのコードがすべて0から127(ASCII)の場合に限りequal
となる(テキストの表現方法を参照)。
(equal "asdf" "ASDF") ⇒ nil
object1かobject2に位置つきシンボルが含まれる場合には、symbols-with-pos-enabled
が非nil
ならequal
はそれらをbare
シンボルとして扱う。それ以外の場合には、コンポーネントを比較することで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 a
b)
はt
をリターンするにも関わらず(equal b
a)
はエラーをシグナルするといった直感に反する結果となることがあります。
この関数はすべてのケースにおいてequal
と同様に振る舞うが、2つの文字列がequal
になるためには、それらが同じテキストプロパティをもつ必要がある。
(equal "asdf" (propertize "asdf" 'asdf t)) ⇒ t
(equal-including-properties "asdf" (propertize "asdf" 'asdf t)) ⇒ nil