ショートハンド(時にリネーム済みシンボルとも呼ばれる)というシンボルは、Lispのソースコードに見られるシンボリック形式です。これらは通常のシンボリック形式と同様ですが、Lispリーダーがこれらに遭遇した際に、異なる、通常はより長いプリント名を持つシンボルを生成するという点が異なります(シンボルの構成要素を参照)。
略記は、意図する記号の正式名称を省略したものと考えると分かりやすいでしょう。とはいえ、略記をAbbrevシステム(AbbrevsとAbbrev Expansionを参照)と混同しないようご注意ください。
ショートハンドを用いることで、Emacs Lispの名前空間の作法をより扱いやすくできます。すべてのシンボルは単一のobarrayに格納されるため(シンボルの作成とインターニングを参照)、プログラマは通常、各シンボル名の先頭に、そのシンボルの由来となるライブラリ名を付加します。例えば、関数text-property-search-forwardとtext-property-search-backwardはいずれもtext-property-search.elライブラリに属しています(ロードを参照)。シンボル名に適切に接頭辞を付けることで、異なるライブラリに属し、したがって異なる役割を持つ、似た名前のシンボル同士の衝突を効果的に防ぐことができます。しかし、こうした慣習では通常、非常に長いシンボル名が生成され、次第に入力や読解が不便になります。ショートハンドは、こうした問題を簡潔に解決します。
この変数の値は、要素が (shorthand-prefix
. longhand-prefix)
という形式を持つアリストです。各要素は、Lispリーダーに対し、shorthand-prefix
で始まるすべてのシンボル形式を、あたかも longhand-prefix
で始まっているかのように読み込むよう指示します。
この変数は、ファイルローカル変数でのみ設定できます(The GNU Emacs ManualのLocal Variables in Filesを参照してください)。
架空の文字列操作ライブラリ some-nice-string-utils.el における短縮記法の使用例を以下に示します。
(defun some-nice-string-utils-split (separator s &optional omit-nulls) "A match-data saving variant of `split-string'." (save-match-data (split-string s separator omit-nulls))) (defun some-nice-string-utils-lines (s) "Split string S at newline characters into a list of strings." (some-nice-string-utils-split "\\(\r\n\\|[\n\r]\\)" s))
ご覧の通り、入力するシンボル名が非常に長いため、このコードを読んだり記述したりするのはかなり煩雑です。短縮表記を使えば、これを軽減できます。
(defun snu-split (separator s &optional omit-nulls)
"A match-data saving variation on `split-string'."
(save-match-data (split-string s separator omit-nulls)))
(defun snu-lines (s)
"Split string S into a list of strings on newline characters."
(snu-split "\\(\r\n\\|[\n\r]\\)" s))
;; Local Variables:
;; read-symbol-shorthands: (("snu-" . "some-nice-string-utils-"))
;; End:
2つの抜粋は見た目こそ異なりますが、Lispリーダーで処理されるとほぼ同一になります。どちらも全く同じシンボルがインターニングされます(シンボルの作成とインターニングを参照)。したがって、これら2つのファイルのいずれかをロードまたはバイトコンパイルしても、結果は同等になります。2番目のバージョンで使用されている短縮記法
snu-split と snu-lines
は、obarray にインターニングされません。これは、短縮記法が使用されている箇所にポイントを移動し、ElDoc(The GNU Emacs Manual の ファイル内のローカル変数を参照)が、エコーエリアにポイント直下のシンボルの実際の正式名称をヒントとして表示するのを待つことで容易に確認できます。
read-symbol-shorthands はファイルローカル変数であるため、some-nice-string-utils-lines.el に依存する複数のライブラリが、異なる
短縮記法を用いて同一のシンボルを参照したり、あるいは短縮記法を全く使用しなかったりする可能性があります。次の例では、my-tricks.el ライブラリは snu- ではなく
sns- というプレフィックスを用いてシンボル some-nice-string-utils-lines を参照しています。
(defun t-reverse-lines (s) (string-join (reverse (sns-lines s)) "\n")
;; Local Variables:
;; read-symbol-shorthands: (("t-" . "my-tricks-")
;; ("sns-" . "some-nice-string-utils-"))
;; End:
なお、同一ファイル内に、一方が他方のプレフィックスとなる2つのショートハンドがある場合、より長い方のショートハンドが優先的に試行されます。これは、ファイルのローカル変数セクションでショートハンドを指定した順序に関わらず発生します。
'(
t//foo ; reads to 'my-tricks--foo', not 'my-tricks-/foo'
t/foo ; reads to 'my-tricks-foo'
)
;; Local Variables:
;; read-symbol-shorthands: (("t/" . "my-tricks-")
;; ("t//" . "my-tricks--"))
;; End:
速記変換を規定する規則には、2つの例外があります。
- や /= を短縮接頭辞として使用することは可能ですが、それによってそれらの名称が持つ算術的な 関数 が上書きされることはありません。
短縮記法は、Lispリーダーによって自動的に展開されます。リーダーを介さずにシンボル名に read-symbol-shorthands
を適用したい場合(例えば、そのシンボルが別のバッファ(ミニバッファなど)由来である場合など)は、shorthands-to-longhand
を使用できます。同様に、バッファ内でシンボルを探す場合は、shorthands-of-symbol
を用いることで、考えられるすべての短縮記法を検討できます。
短縮名が string であるシンボルの正式名称(いわゆる longhand 形式)を返します。常に文字列を返し、string で短縮表記が一切使用されていない場合は、単に string をそのまま返します。
指定されたシンボル名の表記方法の候補をすべてリスト形式で返します。引数 string-or-symbol
にはシンボルまたはその名称を指定でき、戻り値は文字列のリストとなります。なお、戻り値には引数の省略形のみが含まれ、正式名称は含まれないため、戻り値が
nil となることは一般的かつ通常のことです。
文字列 string を、intern と同様に
obarray obarray にインターニングします。ただし、read-symbol-shorthands に従うため、インターニング前に string 内の省略記法(該当する場合)を展開します。インターニングされたシンボルを返します。
shorthands-internと同様ですが、obarrayにその名前のシンボルが存在しない場合、新しいシンボルをインターニングする代わりにnilを返します。