Next: , Previous: , Up: Symbols   [Contents][Index]


8.3 Creating and Interning Symbols

GNU Emacs Lispでシンボルが作成される方法を理解するには、Lispがシンボルを読み取る方法を理解しなければなりません。Lispは、同じ文字綴りを読み取ったら、毎回同じシンボルを見つけることを保証しなければなりません。これに失敗すると、完全な混乱を招くでしょう。

Lispリーダーがシンボルに出会うと、Lispリーダーは名前のすべての文字を読み取ります。その後Lispリーダーは、obarray(オブジェクト配列)と呼ばれるテーブル内のインデックスを決めるために、これらの文字を“ハッシュ(hash)”します。ハッシュ化(hashing)は何かを照合するのに効果的な方法です。たとえば、Jan Jonesを見つけるときは、電話帳を表紙から1頁ずつ探すのではなく、Jから探し始めます。これは簡単なバージョンのハッシュ化です。obarrayの各要素は、与えられたハッシュコードとともにすべてのシンボルを保持する、バケット(bucket)です。与えられた名前を探すためには、バケットの中からその名前のハッシュコードのすべてのシンボルを探すのが効果的です(同じアイデアは一般的なEmacsのハッシュテーブルでも使用されていますが、これらは異なるデータ型です。Hash Tablesを参照してください)。

探している名前のシンボルが見つかったら、リーダーはそのシンボルを使用します。obarrayにその名前のシンボルが含まれない場合、リーダーは新しいシンボルを作成して、それをobarrayに追加します。特定の名前のシンボルを探して追加することを、インターン(intern)すると言い、これが行なわれた後、そのシンボルはインターンされたシンボル(interned symbol)と呼ばれます。

インターンすることにより、ある特定の名前のシンボルは、それぞれのobarrayに1つだけであることが保証されます。同じ名前のシンボルは他に存在するかもしれませんが、同じobarrayではありません。したがってリーダーは、(同じobarrayを読みつづける限り)同じ名前にたいして、同じシンボルを取得します。

インターンは通常、リーダー内で自動的に発生しますが、他のプログラムがこれを行なう必要がある場合もあります。たとえば、M-xコマンドは、その後ミニバッファーを使用してコマンド名を文字列として取得し、その文字列をインターンして、インターンされたその名前のシンボルを得ます。

すべてのシンボルを含むobarrayはありません。実際、どのobarrayにも含まれないシンボルがいくつかあります。これらは、インターンされていないシンボル(uninterned symbols)と呼ばれます。インターンされていないシンボルも、他のシンボルと同じく4つのセルをもちます。しかし、インターンされていないシンボルへのアクセスを得る唯一の方法は、他の何らかのオブジェクトとして探すか、変数の値として探す方法だけです。

インターンされていないシンボルの作成は、Lispコードを生成するとき有用です。なぜなら、作成されたコード内で変数として使用されているインターンされていないシンボルは、他のLispプログラムで使用されている任意の変数と競合することはありえないからです。

Emacs Lispでは、obarrayはベクターです。ベクター内の各要素がバケットになります。要素の値は、名前がそのバケットにハッシュされるインターンされたシンボル、またはバケットが空のときは0です。インターンされたシンボルは、そのバケット内の次のシンボルへの、内部リンク(ユーザーからは見えない)をもちます。これらのリンクは不可視なので、mapatomsを使用する方法をのぞき(以下参照)、obarray内のすべてのシンボルを探す方法はありません。バケット内のシンボルの順番に、意味はありません。

空のobarrayでは、すべての要素が0なので、(make-vector length 0)でobarrayを作成することができます。obarrayを作成する有効な方法は、これだけです。長さに素数を指定すると、よいハッシュ化がされる傾向があります。2の累乗から1減じた長さも、よい結果を生む傾向があります。

自分でobarrayにシンボルを置かないでください。これはうまくいきません — obarrayに正しくシンボルを入力できるのは、internだけです。

Common Lispに関する注意: Common Lispとは異なり、Emacs Lispは1つのシンボルを複数のobarrayにインターンする方法を提供しません。

以下の関数のほとんどは、引数に名前とobarrayをとります。名前が文字列ではない、またはobarrayがベクターでない場合は、wrong-type-argumentエラーがシグナルされます。

Function: symbol-name symbol

この関数は、symbolの名前を文字列としてreturnします。たとえば:

(symbol-name 'foo)
     ⇒ "foo"

警告: 文字の置き換えにより文字列を変更すると、それはシンボルの名前を変更しますが、obarrayの更新には失敗するので、行なわないでください!

Function: make-symbol name

この関数は、新たに割り当てられた、名前がname(文字列でなかればならない)のインターンされていないシンボルをreturnします。このシンボルの値と関数はvoidで、プロパティーリストはnilです。以下の例では、symの値はfooeqではありません。なぜなら、これは名前が‘foo’のインターンされていないシンボルだからです。

(setq sym (make-symbol "foo"))
     ⇒ foo
(eq sym 'foo)
     ⇒ nil
Function: intern name &optional obarray

この関数は、名前がnameの、インターンされたシンボルをreturnします。オブジェクト配列obarrayの中にそのようなシンボルが存在しない場合、internはあたらしいシンボルを作成してobarrayに追加し、それをreturnします。obarrayが省略された場合、グローバル変数obarrayの値が使用されます。

(setq sym (intern "foo"))
     ⇒ foo
(eq sym 'foo)
     ⇒ t

(setq sym1 (intern "foo" other-obarray))
     ⇒ foo
(eq sym1 'foo)
     ⇒ nil

Common Lispに関する注意: Common Lispでは、既存のシンボルをobarrayにインターンできます。Emacs Lispでは、internの引数はシンボルではなく文字列なので、これを行なうことはできません。

Function: intern-soft name &optional obarray

この関数は、obarray内の名前がnameのシンボル、obarrayにその名前のシンボルが存在しない場合はnilをreturnします。したがって、与えられた名前のシンボルがすでにインターンされているかテストするために、intern-softを使用することができます。obarrayが省略された場合は、グローバル変数obarrayの値が使用されます。

引数nameにはシンボルも使用できます。この場合、指定されたobarrayにnameがインターンされていればname、それ以外はnilをreturnします。

(intern-soft "frazzle")        ; そのようなシンボルは存在しない。
     ⇒ nil
(make-symbol "frazzle")        ; インターンされていないシンボルを作成する。
     ⇒ frazzle
(intern-soft "frazzle")        ; そのようなシンボルは見つからない。
     ⇒ nil
(setq sym (intern "frazzle"))  ; インターンされたシンボルを作成する。
     ⇒ frazzle
(intern-soft "frazzle")        ; シンボルが見つかった!
     ⇒ frazzle
(eq sym 'frazzle)              ; そして、それは同じシンボル。
     ⇒ t
Variable: obarray

この変数は、internおよびreadで使用される、標準のobarrayです。

Function: mapatoms function &optional obarray

この関数は、オブジェクト配列obarrayの中のシンボルに1つにたいして、1度ずつfunctionを呼び出し、その後nilをreturnします。obarrayが省略された場合は、通常のシンボルにたいする標準のオブジェクト配列obarrayの値がデフォルトになります。

(setq count 0)
     ⇒ 0
(defun count-syms (s)
  (setq count (1+ count)))
     ⇒ count-syms
(mapatoms 'count-syms)
     ⇒ nil
count
     ⇒ 1871

mapatomsを使用する他の例については、Accessing Documentationdocumentationを参照してください。

Function: unintern symbol obarray

この関数は、オブジェクト配列obarrayから、symbolを削除します。obarrayの中にsymbolが存在しない場合、uninternは何も行ないません。obarraynilの場合は、現在のobarrayが使用されます。

symbolにシンボルではなく文字列を与えた場合、それはシンボルの名前を意味します。この場合、uninternは、(もしあれば)obarrayからその名前のシンボルを削除します。そのようなシンボルが存在する場合、uninternは何も行ないません。

uninternがシンボルを削除した場合はt、それ以外はnilをreturnします。


Next: , Previous: , Up: Symbols   [Contents][Index]