GNU Emacs Lispでシンボルが作成される方法を理解するには、Lispがシンボルを読み取る方法を理解しなければなりません。Lispは同じコンテキストで同じ文字シーケンスを読み取ったら、毎回同じシンボルを見つけることを保証しなければなりません。これに失敗すると、完全な混乱を招くでしょう。
Lispリーダーがソースコード中にシンボルを参照する名前を発見した際には、プログラマーが意図したシンボルを見つけるためにobarrayと呼ばれるテーブルを調べます。obarrayとは名前でインデックス付けされた順序付けされていないシンボルのコンテナのことです。
Lispリーダーは“ショートハンド”も考慮します。プログラマーがショートハンドを提供している場合には、完全な形式でソースコード中に出現しないシンボルであっても、リーダーはシンボルを見つけることができます。
探している名前のシンボルが見つかったら、リーダーはそのシンボルを使用します。obarrayにその名前のシンボルが含まれなければ、リーダーは新しいシンボルを作成してそれをobarrayに追加します。特定の名前のシンボルを探して追加することをインターン(intern)と言い、これが行なわれた後はそのシンボルはインターンされたシンボル(interned symbol)と呼ばれます。
インターンすることによりある特定の名前のシンボルは、各obarrayに1つだけであることが保証されます。同じ名前のシンボルが他に存在するかもしれませんが、同じobarrayには存在しません。したがってリーダーは、(同じobarrayを読みつづける限り)同じ名前にたいして同じシンボルを取得します。
インターンは通常はリーダー内で自動的に発生しますが、他のプログラムがこれを行ないたい場合もあるかもしれません。たとえばM-xコマンドはその後にミニバッファーを使用してコマンド名を文字列として取得して、その文字列をインターンしてからインターンされたその名前のシンボルを得ます。別の例として、照合する人名それぞれをシンボル名としてインターンする架空の電話帳プログラムは、たとえそれがobarrayに含まれていなくても、誰かが最後にそれを照合した際に情報をアタッチできるようにする場合などです。
すべてのシンボルを含むobarrayはありません。実際にどのobarrayにも含まれないシンボルがいくつかあります。これらはインターンされていないシンボル(uninterned symbols)と呼ばれます。インターンされていないシンボルも、他のシンボルと同じく4つのセルをもちます。しかしインターンされていないシンボルへのアクセスを得る唯一の方法は、他の何らかのオブジェクトとして探すか、変数の値として探す方法だけです。インターンされていないシンボルはLispコード生成時に有用な場合があります。以下を参照してください。
Common Lispに関する注意: Common Lispとは異なりEmacs Lispでは複数の異なる“パッケージ”における同一の名前のインターンは提供されていないので、異なるパッケージごとに同じ名前のシンボルが複数作成される。Emacs Lispは“ショートハンド”と呼ばれる別の名前空間システムを提供する(ショートハンドを参照)。
この関数はobarrayを新たに作成してリターンする。オプションのsizeは保持できるシンボルの個数を指定するが、obarrayは必要に応じて拡張されるので何らかのメリットが得られるのは稀であろう。
この関数はobjectがobarrayならt
、それ以外はnil
をリターンする。
以下の関数のほとんどは、引数に名前とobarrayをとります。名前が文字列以外、またはobarrayがobarrayオブジェクト以外ならwrong-type-argument
エラーがシグナルされます。
この関数はsymbolの名前を文字列としてリターンする。たとえば:
(symbol-name 'foo) ⇒ "foo"
警告: この関数がリターンした文字列は絶対変更してはならない。これを行うことによってEmacsの機能が損なわれるかもしれず、Emacsのクラッシュすら招きかねない。
インターンされていないシンボルの作成は、Lispコードを生成するとき有用です。なぜなら作成されたコード内で変数として使用されているインターンされていないシンボルは、他のLispプログラムで使用されている任意の変数と競合することはありえないからです。
この関数は新たに割り当てられた、名前がname(文字列でなければならない)であるような、インターンされていないシンボルをリターンする。このシンボルの値と関数はvoidで、プロパティリストはnil
。以下の例ではsym
の値はfoo
とeq
ではない。なぜならこれは名前が‘foo’という、インターンされていないシンボルだからである。
(setq sym (make-symbol "foo")) ⇒ foo (eq sym 'foo) ⇒ nil
この関数はmake-symbol
を使用してprefixにgensym-counter
を付加した名前のシンボルをリターンする。更にこの関数を複数回呼び出しても同一名のシンボルが生成されないことを保証するためにカウンターを増加する。プレフィックスのデフォルトは"g"
。
意図せず生成したコードのプリント表現をインターンした際の問題を避けるために、make-symbol
ではなくgensym
の使用をお勧めします。(プリント表現と読み取り構文を参照)。
この関数は名前がnameであるような、インターンされたシンボルをリターンする。オブジェクト配列obarrayの中にそのようなシンボルが存在しなければ、intern
は新たにシンボルを作成してobarrayに追加してそれをリターンする。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
の引数はシンボルではなく文字列なのでこれを行なうことはできない。
この関数はobarray内の名前がnameのシンボル、obarrayにその名前のシンボルが存在しなければnil
をリターンする。したがって与えられた名前のシンボルがすでにインターンされているかテストするために、intern-soft
を使用することができる。obarrayが省略されるとグローバル変数obarray
の値が使用される。
引数nameにはシンボルも使用できる。この場合、指定されたobarrayにnameがインターンされていればname、それ以外ならnil
をリターンする。
(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
この変数はintern
とread
が使用する標準のobarrayである。
この関数はオブジェクト配列obarrayの中の各シンボルにたいして、functionを一度呼び出しその後nil
をリターンする。obarrayが省略されると、通常のシンボルにたいする標準のオブジェクト配列obarray
の値がデフォルトになる。
(setq count 0) ⇒ 0 (defun count-syms (s) (setq count (1+ count))) ⇒ count-syms (mapatoms 'count-syms) ⇒ nil count ⇒ 1871
mapatoms
を使用する他の例については、ドキュメント文字列へのアクセスのdocumentation
を参照のこと。
この関数はオブジェクト配列obarrayからsymbolを削除する。obarrayの中にsymbol
が存在しなければ、unintern
は何も行なわない。obarrayがnil
なら現在のobarrayが使用される。
symbolにシンボルではなく文字列を与えると、それはシンボルの名前を意味する。この場合、unintern
は(もしあれば)obarrayからその名前のシンボルを削除する。そのようなシンボルが存在するならunintern
は何も行なわない。
unintern
がシンボルを削除したらt
、それ以外はnil
をリターンする。
この関数はobarrayからすべてのシンボルを削除する。