2.8 同等性のための述語

ここでは2つのオブジェクトの同一性をテストする関数を説明します。(たとえば文字列などの)特定の型のオブジェクト同士で内容の同一性をテストするには、別の関数を使用します。これらの述語にたいしては、そのデータ型を説明する適切なチャプターを参照してください。

Function: eq object1 object2

この関数はobject1object2が同じオブジェクトならt、それ以外はnilをリターンする。

object1object2が同じ名前をもつシンボルなら、通常は同じオブジェクトだが例外もある。シンボルの作成とinternを参照のこと。他の非数値型(リストやベクター、文字列などの)にたいしては、同じ内容(または要素)の2つの引数が両者eqである必要はない。これらが同じオブジェクトの場合だけeqであり、その場合には一方の内容を変更するともう一方の内容にも同じ変更が反映される。

object1object2が異なるタイプや値をもつ数値なら同じオブジェクトではなく、eqnilをリターンする。同じ値をもつfixnumなら同じオブジェクトであり、eqtをリターンする。別個に計算されてたまたま同じ値をもち、かつ非fixnumタイプの同じ数値型なら、それらは同じかもしれないし違うかもしれず、Lispインタープリターが作成したオブジェクトが1つか2つかに依存してeqtnilをリターンする。

object1object2が位置つきシンボル(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)しないこと。バイトコンパイラーがそれらの落し込みを行っていたら、同一コンテンツをもつ別のリテラルオブジェクトに影響があるかもしれない。

Function: equal object1 object2

この関数はobject1object2が同じ構成要素をもつなら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

object1object2に位置つきシンボルが含まれる場合には、symbols-with-pos-enabledが非nilならequalはそれらをbare シンボルとして扱う。それ以外の場合には、コンポーネントを比較することで2つの位置つきシンボルを比較する。位置つきシンボルを参照のこと。

その他のオブジェクトは、それらがeqの場合のみequalとみなされる。たとえば個別の2つのバッファーは、たとえバッファーのテキスト的なコンテンツが同一であってもequalとみなされることはない。

equalでは等価性は再帰的に定義されています。たとえば2つのコンスセルxyを与えると、(equal x y)は、以下の式の両方がtをリターンする場合だけtをリターンします:

(equal (car x) (car y))
(equal (cdr x) (cdr y))

したがって循環リストの比較はエラーとなるような深い再帰を引き起こすかもしれず、(equal a b)tをリターンするにも関わらず(equal b a)はエラーをシグナルするといった直感に反する結果となることがあります。

Function: equal-including-properties object1 object2

この関数はすべてのケースにおいてequalと同様に振る舞うが、2つの文字列がequalになるためには、それらが同じテキストプロパティをもつ必要がある。

(equal "asdf" (propertize "asdf" 'asdf t))
     ⇒ t
(equal-including-properties "asdf"
                            (propertize "asdf" 'asdf t))
     ⇒ nil

Footnotes

(2)

とはいえ別個の関数オブジェクトの等価性は一般的には保証できません。


This page has generated for branch:work/emacs-30_69b16e5c63840479270d32f58daea923fe725b90, commit:5e3f74b56ff47b5bcef2526c70f53f749bbd45f6 to check Japanese translation.