GNU Emacs Lisp Reference Manual

For Emacs Version 24.5

Revision 3.1, October 2014

by Bil Lewis, Dan LaLiberte, Richard Stallman,
the GNU Manual Group, et al.

This is the GNU Emacs Lisp Reference Manual corresponding to Emacs version 24.5.

Copyright © 1990–1996, 1998–2015 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Sections being “GNU General Public License,” with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”

(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual. Buying copies from the FSF supports it in developing GNU and promoting software freedom.”



Published by the Free Software Foundation
51 Franklin St, Fifth Floor
Boston, MA 02110-1301
USA
ISBN 1-882114-74-4



Cover art by Etienne Suvasa.


[ < ] [ > ]   [Contents] [Index] [ ? ]

Emacs Lisp

This is the GNU Emacs Lisp Reference Manual corresponding to Emacs version 24.5.

Copyright © 1990–1996, 1998–2015 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Sections being “GNU General Public License,” with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”

(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual. Buying copies from the FSF supports it in developing GNU and promoting software freedom.”


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Introduction

GNU Emacsテキストエディターのほとんどの部分は、Emacs Lispと呼ばれるプログラミング言語で記述されています。新しいコードをEmacs Lispで記述して、このエディターの拡張としてインストールできます。しかしEmacs Lispは、単なる“拡張言語”を越えた言語であり、それ自体で完全なコンピュータープログラミング言語です。他のプログラミング言語で行なうすべてのことに、この言語を使用できます。

Emacs Lispはエディターの中で使用するようにデザインされているので、テキストのスキャンやパースのための特別な機能をもち、同様にファイル、バッファー、ディスプレー、サブプロセスを処理する機能をもちます。Emacs Lispは編集機能と密に統合されています。したがって編集コマンドはLispプログラムから簡単に呼び出せる関数であり、カスタマイズのためのパラメーターは普通のLisp変数です。

このマニュアルはEmacs Lispの完全な記述を試みます。初心者のためのEmacs Lispのイントロダクションは、Free Software Foundationからも出版されている、Bob ChassellのAn Introduction to Emacs Lisp Programmingを参照してください。このマニュアルは、Emacsを使用した編集に熟知していることを前提としています。これの基本的な情報については、The GNU Emacs Manualを参照してください。

おおまかに言うと、前の方のチャプターでは多くのプログラミング言語に対応するEmacs Lispの機能について説明し、後のチャプターではEmacs Lispに特異な機能や、特に編集に関連した機能を説明します。

これは Emacs 24.5に対応したGNU Emacs Lisp Reference Manualです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Caveats

このマニュアルは幾多のドラフトを経てきました。ほとんど完璧ではありますが、不備がないとも言えません。(ほとんどの特定のモードのように)それらが副次的であるとか、まだ記述されていないという理由により、カバーされていないトピックもあります。わたしたちがそれらを完璧に扱うことはできないので、いくつかの部分は意図的に省略しました。

このマニュアルは、それがカバーしている事柄については完全に正しくあるべきあり、故に、特定の説明テキスト、チャプターやセクションの順番にたいしての批判に開かれているべきです。判りにくかったり、このマニュアルでカバーされていない何かを学ぶためにソースを見たり実験から学ぶ必要があるなら、このマニュアルはおそらくフィクスされるべきなのかもしれません。わたしたちにそれを教えてください。

このマニュアルを使用するときは、間違いを見つけたらすぐに訂正を送ってください。関数または間数グループの単純な現実例を考えたときは、ぜひそれを記述して送ってください。それが妥当ならコメントでノード名と関数名や変数名を参照してください。あなたが訂正を求めるエディションのバージョンも示してください。

M-x report-emacs-bugを使用してコメントや訂正を送ってください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 Lisp History

Lisp(LISt Processing language: リスト処理言語)は、MIT(Massachusetts Institute of Technology: マサチューセッツ工科大学)で、AI(artificial intelligence: 人工知能)の研究のために、1950年代末に最初に開発されました。Lisp言語の強力なパワーは、編集コマンドの記述のような、他の目的にも適っています。

長年の間に何ダースものLisp実装が構築されてきて、それぞれ特異な点があります。これらの多くは、1960年代にMITのProject MACで記述された、Maclispに影響を受けています。最終的に、Maclisp後裔の実装者は共同して、Common Lispと呼ばれる標準のLispシステムを開発しました。その間に、MITのGerry SussmanとGuy Steeleにより、簡潔だがとても強力なLisp方言である、Schemeが開発されました。

GNU Emacs LispはMaclispから多く、Common Lispから少し影響を受けています。Common Lispを知っている場合、多くの類似点に気がつくでしょう。しかしCommon Lispの多くの機能は、GNU Emacsが要求するメモリー量を削減するために、省略されるか単純化されています。ときには劇的に単純化がされているために、Common Lispユーザーは混乱するかもしれません。わたしたちは時折GNU Emacs LispがCommon Lispと異なるか示すでしょう。Common Lispを知らない場合、それについて心配する必要はありません。このマニュアルは自己完結しています。

cl-libライブラリーを通じて、Common Lispをかなりエミュレートできます。Overview in Common Lisp Extensionsを参照してください。

Emacs LispはSchemeの影響は受けていません。しかしGNUプロジェクトにはGuileと呼ばれるScheme実装があります。拡張が必要な新しいGNUソフトウェアーでは、Guileを使用します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Conventions

このセクションでは、このマニュアルで使用する表記規約を説明します。あなたはこのセクションはスキップして、後で参照したいと思うかもしれません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.1 Some Terms

このマニュアルでは、“Lispリーダー”および“Lispプリンター”という用語で、Lispのテキスト表現を実際のLispオブジェクトに変換したり、その逆を行なうLispルーチンを参照します。詳細については、Printed Representation and Read Syntaxを参照してください。あなた、つまりこのマニュアルを読んでいる人のことは“プログラマー”と考えて“あなた”と呼びます。“ユーザー”とは、あなたの記述したものも含めて、Lispプログラムを使用する人を指します。

Lispコードの例は、(list 1 2 3)のようなフォーマットです。 Examples of Lisp code are formatted like this: (list 1 2 3). メタ構文変数(metasyntactic variables)を表す名前や、説明されている関数の引数名前は、first-numberのような形式です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.2 nil and t

Emacs Lispでは、シンボルnilには3つの異なる意味があります。1つ目は‘nil’という名前のシンボル、2つ目は論理値のfalse、3つ目は空リスト — つまり要素が0のリストです。変数として使用した場合、nilは常に値nilをもちます。

Lispリーダーに関する限り、‘()’と‘nil’は同一です。これらは同じオブジェクト、つまりシンボルnilを意味します。このシンボルを異なる方法で記述するのは、完全に人間の読み手を意図したものです。Lispリーダーが‘()’か‘nil’のどちらかを読み取った後は、プログラマーが実際にどちらの表現で記述したかを判断する方法はありません。

このマニュアルでは、空リストを意味することを強調したいときは()と記述し、論理値のfalseを意味することを強調したいときはnilと記述します。この慣習はLispプログラムで使用してもよいでしょう。

(cons 'foo ())                ; 空リストを強調します
(setq foo-flag nil)           ; 論理値のfalseを強調します

論理値が期待されているコンテキストでは、非niltrueと判断されます。しかし論理値のtrueを表す好ましい方法はtです。trueを表す値を選択する必要があり、他に選択の根拠がない場合は、tを使用してください。シンボルtは、常に値tをもちます。

Emacs Lispでは、niltは、常に自分自身を評価する、特別なシンボルです。そのためプログラムでこれらを定数として使用する場合、クォートする必要はありません。これらの値を変更使用と試みると、結果はsetting-constantエラーとなります。Variables that Never Changeを参照してください。

Function: booleanp object

objectが、2つのカノニカルなブーリーン値(tまたはnil)の場合は、非nilをリターンします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.3 Evaluation Notation

評価することができるLisp式のことを、フォーム(form)と呼びます。フォームの評価により、常に結果としてLispオブジェクトが生成されます。このマニュアルの例では、これを‘’で示します:

(car '(1 2))
     ⇒ 1

これは、“(car '(1 2))を評価すると1になる”と読むことができます。

フォームがマクロ呼び出しの場合、それは評価されるための新しいLispのフォームに展開されます。展開された結果は‘’で示します。展開されたフォームを評価した結果を示すこともあれば、示さない場合もあります。

(third '(a b c))
     → (car (cdr (cdr '(a b c))))
     ⇒ c

1つのフォームを説明するために、同じ結果を生成する別のフォームを示すこともあります。完全に等価な2つのフォームは、‘’で示します。

(make-sparse-keymap) ≡ (list 'keymap)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.4 Printing Notation

このマニュアルの例の多くは、それらが評価されるときにテキストをプリントします。(*scratch*バッファーのような)Lisp Interactionバッファーでコード例を実行する場合、プリントされるテキストはそのバッファーに挿入されます。(関数eval-regionで評価するなど)他の方法でコード例を実行する場合、プリントされるテキストはエコーエリアに表示されます。

このマニュアルの例はプリントされるテキストがどこに出力されるかに関わらず、それを‘-|’で示します。フォームを評価することにより戻される値は、‘’とともに後続の行で示します。

(progn (prin1 'foo) (princ "\n") (prin1 'bar))
     -| foo
     -| bar
     ⇒ bar

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.5 Error Messages

エラーをシグナルする例も、いくつかあります。これは通常、エコーエリアにエラーメッセージを表示します。エラーメッセージの行は、‘error→’で始まります。‘error→’自体は、エコーエリアに表示されないことに注意してください。

(+ 23 'x)
error→ Wrong type argument: number-or-marker-p, x

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.6 Buffer Text Notation

バッファー内容の変更を説明する例もあり、それらの例ではテキストの“before(以前)”と“after(以後)”のバージョンを示します。それらの例では、バッファー内容の該当する部分を、ダッシュを用いた2行の破線(バッファー名を含む)で示します。さらに、‘’はポイントの位置を示します(もちろんポイントのシンボルは、バッファーのテキストの一部ではなく、それはポイントが現在配されている2つの文字のの位置を示します)。

---------- Buffer: foo ----------
This is the ∗contents of foo.
---------- Buffer: foo ----------

(insert "changed ")
     ⇒ nil
---------- Buffer: foo ----------
This is the changed ∗contents of foo.
---------- Buffer: foo ----------

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.7 Format of Descriptions

このマニュアルでは関数(function)、変数(variable)、コマンド(command)、ユーザーオプション(user option)、スペシャルフォーム(special form)を、統一されたフォーマットで記述します。記述の最初の行には、そのアイテムの名前と、もしあれば引数(argument)が続きます。 そのアイテムの属するカテゴリー(function、variableなど)は、行の先頭に表示します。 それ以降の行は説明行で、例を含む場合もあります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.7.1 A Sample Function Description

関数の記述では、関数の名前が最初に記述されます。同じ行に引数の名前のリストが続きます。引数の値を参照するために、引数の名前は記述の本文にも使用されます。

引数リストの中にキーワード&optionalがある場合、その後の引数が省略可能であることを示します(省略された引数のデフォルトはnilです)。その関数を呼び出すときは、&optionalを記述しないでください。

キーワード&rest(これの後には1つの引数名を続けなければなりません)は、その後に任意の引数を続けることができることを表します。&restの後に記述された引数名の値には、その関数に渡された残りのすべての引数がリストとしてセットされます。この関数を呼び出すときは、&restを記述しないでください。

以下はfooという架空の関数(function)の説明です:

Function: foo integer1 &optional integer2 &rest integers

関数foointeger2からinteger1を減じてから、その結果に残りすべての引数を加えます。integer2が与えられなかった場合、デフォルトして数値19が使用されます。

(foo 1 5 3 9)
     ⇒ 16
(foo 5)
     ⇒ 14

より一般的には、

(foo w x y…)
≡
(+ (- x w) y…)

慣例として引数の名前には、(たとえばintegerinteger1bufferのような)期待されるタイプ名が含めます。(buffersのような)複数形のタイプは、しばしばそのタイプのオブジェクトのリストを意味します。objectのような引き数名は、それが任意のタイプであることを表します(Emacsオブジェクトタイプのリストは、Lisp Data Typesを参照してください)。他の名前をもつ引数(たとえばnew-file)は、関数に固有の引数で、関数がドキュメント文字列をもつ場合、引数のタイプはその中で説明されるべきです(Documentationを参照してください)。

&optional&restにより修飾される引数の、より完全な説明は、Lambda Expressionsを参照してください。

コマンド(command)、マクロ(macro)、スペシャルフォーム(special form)の説明も同じフォーマットをもちますが、‘Function’が‘Command’、‘Macro’、‘Special Form’に置き換えられます。コマンドは単にインタラクティブに呼び出すことができる関数です。マクロは関数とは違う方法(引数は評価されません)で引数を処理しますは、同じ方法で記述されます。

マクロとスペシャルフォームにたいする説明には、特定のオプション引数や繰り替えされる引数のために、より複雑な表記が使用されます。なぜなら引数リストが、より複雑な方法で別の引数に分離されるからです。‘[optional-arg]’はoptional-argがオプションであることを意味し、‘repeated-args’は0個以上の引数を表します。カッコ(parentheses)は、複数の引数をリスト構造の追加レベルにグループ化するのに使用されます。以下は例です:

Special Form: count-loop (var [from to [inc]]) body…

この架空のスペシャルフォームは、 bodyフォームを実行してから変数varをインクリメントするループを実装します。最初の繰り返しでは変数は値fromをもちます。以降の繰り返しでは、変数は1(incが与えられた場合はinc)増加されます。vartoに等しい場合、bodyを実行する前にループをexitします。以下は例です:

(count-loop (i 0 10)
  (prin1 i) (princ " ")
  (prin1 (aref vector i))
  (terpri))

fromtoが省略された場合、ループを実行する前にvarnilがバインドされ、繰り返しの先頭においてvarが非nilの場合は、ループをexitします。以下は例です:

(count-loop (done)
  (if (pending)
      (fixit)
    (setq done t)))

このスペシャルフォームでは、引数fromおよびtoはオプションですが、両方を指定するか、両方を未指定にしなければなりません。これらの引数が与えられた場合、オプションでincも同様に指定することができます。これらの引数は、フォームのすべての残りの要素を含むbodyと区別するために、引数varとともにリストにグループ化されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.7.2 A Sample Variable Description

変数(variable)とは、オブジェクトにバインド(bind)(またはset)される名前です。変数がバインドされたオブジェクトのことを値(value)と呼びます。このような場合、その変数が値をもつ、という言い方もします。ほとんどすべての変数はユーザーがセットすることができますが、特にユーザーが変更できる特定の変数も存在し、これらはユーザーオプション(user options)と呼ばれます。通常の変数およびユーザーオプションは、関数と同様のフォーマットを使用して説明されますが、それらには引数がありません。

以下は架空の変数electric-future-mapにたいする説明です。

Variable: electric-future-map

この変数の値はElectric Command Futureモードで使用される完全なキーマップです。このマップの関数により、まだ実行していないコマンドの編集が可能になります。

ユーザーオプションも同じフォーマットをもちますが、‘Variable’が‘User Option’に置き換えられます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Version Information

以下の機能は使用しているEmacsに関する情報を提供します。

Command: emacs-version &optional here

この関数は実行しているEmacsのバージョンを説明する文字列をreturnそます。バグレポートにこの文字列を含めるときに役立ちます。

(emacs-version)
  ⇒ "GNU Emacs 23.1 (i686-pc-linux-gnu, GTK+ Version 2.14.4)
             of 2009-06-01 on cyd.mit.edu"

hereが非nilの場合、関数はテキストをバッファーのポイントの前に挿入し、nilをreturnします。この関数がインタラクティブに呼び出された場合は、同じ情報をエコーエリアに出力しますが、プレフィクス引数を与えた場合は、hereが非nilになります。

Variable: emacs-build-time

この変数の値は、Emacsがビルドされた日時を示します。値は、current-timeの値と同様の、4つの整数からなるリストです(Time of Dayを参照してください)。

emacs-build-time
     ⇒ (20614 63694 515336 438000)
Variable: emacs-version

この変数の値は実行中のEmacsのバージョンで、"23.1.1"のような文字列です。この文字列の最後の数字は、実際にはEmacsのリリースバージョン番号の一部ではなく、任意のディレクトリーにおいてEmacsがビルドされる度にインクリメントされます。"22.0.91.1"のように4つの数字から構成される値は、それがリリースではないテストバージョンであることを示します。

Variable: emacs-major-version

Emacsのメジャーバージョン番号を示す整数です。Emacs 23.1では、値は23になります。

Variable: emacs-minor-version

Emacsのマイナーバージョン番号をしめす整数です。Emacs 23.1では、値は1になります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 Acknowledgments

このマニュアルは当初、Robert Krawitz、Bil Lewis、Dan LaLiberte、Richard M. Stallman、Chris Welty、GNUマニュアルグループのボランティアーにより、数年を費やして記述されました。Robert J. Chassellはこのマニュアルのレビューと編集をDefense Advanced Research Projects Agency、ARPA Order 6082のサポートのもとに手助けしてくれ、Computational Logic, IncのWarren A. Hunt, Jr.によりアレンジされました。それ以降も、追加のセクションがMiles Bader、Lars Brinkhoff、Chong Yidong、Kenichi Handa、Lute Kamstra、Juri Linkov、Glenn Morris、Thien-Thi Nguyen、Dan Nicolaescu、Martin Rudalics、Kim F. Storm、Luc Teirlinck、Eli Zaretskii、およびその他の人たちにより記述されました。

Drew Adams、Juanma Barranquero、Karl Berry、Jim Blandy、Bard Bloom、Stephane Boucher、David Boyes、Alan Carroll、Richard Davis、Lawrence R. Dodd、Peter Doornbosch、David A. Duff、Chris Eich、Beverly Erlebacher、David Eckelkamp、Ralf Fassel、Eirik Fuller、Stephen Gildea、Bob Glickstein、Eric Hanchrow、Jesper Harder、George Hartzell、Nathan Hess、Masayuki Ida、Dan Jacobson、Jak Kirman、Bob Knighten、Frederick M. Korz、Joe Lammens、Glenn M. Lewis、K. Richard Magill、Brian Marick、Roland McGrath、Stefan Monnier、Skip Montanaro、John Gardiner Myers、Thomas A. Peterson、Francesco Potortì、Friedrich Pukelsheim、Arnold D. Robbins、Raul Rockwell、Jason Rumney、Per Starbäck、Shinichirou Sugou、Kimmo Suominen、Edward Tharp、Bill Trost、Rickard Westman、Jean White、Eduard Wiebe、Matthew Wilding、Carl Witty、Dale Worley、Rusty Wright、David D. Zuhnにより訂正が提供されました。

より完全な貢献者のリストは、Emacsソースリポジトリーの関連する変更ログエントリーを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2 Lisp Data Types

Lispのオブジェクト(object)とは、Lispおプログラムにより操作されるデータです。型(type)データ型(data type)は、可能なオブジェクトの集合を意味します。

すべてのオブジェクトは少なくとも1つの型に属します。同じ型のオブジェクトは、同様な構造をもち、通常は同じコンテキストで使用されます。型は重複でき、オブジェクトは複数の型に属することができます。結果として、あるオブジェクトが特定の型に属するかどうかを尋ねることはできますが、オブジェクトが“その”型だけに属するかどうかは決定できません。

多くはありませんがEmacsにはいくつかの基本オブジェクト型が組み込まれています。これらの型は、他のすべての型を構成するもとであり、基本型(primitive types)と呼ばれます。すべてのオブジェクトはただ1つの基本型に属します。これらの型には、整数(integer)浮動小数点数(float)コンス(cons)シンボル(symbol)文字列(string)ベクター(vector)ハッシュテーブル(hash-table)サブルーチン(subr)バイトコード関数(byte-code function)、およびbufferのような編集に関連した特別な型(Editing Typesを参照してください)が含まれます。

基本型にはそれぞれ、オブジェクトがその型のメンバーかどうかのチェックを行なう、対応するLisp関数があります。

他の多くの言語とは異なり、Lispのオブジェクトは自己記述(self-typing)的です。オブジェクトの基本型は、オブジェクト自体に暗に含まれます。たとえばオブジェクトがベクターの場合、それを数字として扱うことはできません。Lispはベクターが数字でないことを知っているのです。

多くの言語では、プログラマーは各変数にたいしてデータ型を宣言しなければならず、コンパイラーは型を知っていますが、データの中に型はありません。Emacs Lispには、このような型宣言はありません。Lisp変数は任意の型の値をもつことができ、変数に保存した値と型を記憶します(実際には、特定の型の値だけをもつことができる少数のEmacs Lisp変数があります。Variables with Restricted Valuesを参照してください)。

このチャプターでは、GNU Emacs Lispの各標準型の意味、プリント表現(printed representation)、入力構文(read syntax)を説明します。これらのデータ型を使用する方法についての詳細は、以降のチャプターを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 Printed Representation and Read Syntax

オブジェクトのプリント表現(printed representation)とは、オブジェクトにたいしてLispプリンター(関数prin1)が生成する出力のフォーマットです。すべてのデータ型は一意なプリント表現をもちます。オブジェクトの入力構文(read syntax)とは、オブジェクトにたいしてLispリーダー(関数read)が受け取る入力のフォーマットです。これは一意である必要はありません。多くの種類のオブジェクトが複数の構文をもちます。Reading and Printing Lisp Objectsを参照してください。

ほとんどの場合、オブジェクトのプリント表記が、入力構文としても使用されます。しかしLispプログラム内の定数とすることに意味が無いいくつかの型には、入力構文がありません。これらのオブジェクトはハッシュ表記(hash notation)でプリントされ、‘#<’、説明的な文字列(典型的には型名にオブジェクトの名前を続けたもの)、‘>’で構成される文字列です。たとえば:

(current-buffer)
     ⇒ #<buffer objects.texi>

ハッシュ表気は読み取ることができないので、Lispリーダーは‘#<’に遭遇すると、常にエラーinvalid-read-syntaxをシグナルします。

他の言語では、式はテキストであり、これ以外の形式はありません。Lispでは、第一に式はLispオブジェクトであって、オブジェクトの入力構文であるテキストは副次的なものに過ぎません。たいてい、この違いを強調する必要はありませんが、このことを心に留めておかないと、たまに混乱することがあるでしょう。

インタラクティブに式を評価するとき、Lispインタープリターは最初にそれのテキスト表現を読み取り、Lispオブジェクトを生成してから、そのオブジェクトを評価します(Evaluationを参照してください)。しかし評価と読み取りは、別の処理です。読み取りによりテキストにより表現されたLispオブジェクトを読み取り、Lispオブジェクトがreturnされます。後でオブジェクトは評価されるかもしれないし、評価されないかもしれません。オブジェクトを読み取るための基本的な関数readの説明は、Input Functionsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Comments

コメント(comment)hqあ、プログラム中に記述されたテキストであり、そのプログラムを読む人間ためだけに存在し、プログラムの意味には何の影響ももちません。Lispでは、それが文字列や文字定数にある場合をのぞき、セミコロン(‘;’)でコメントが開始されます。行の終端までがコメントになります。Lispリーダーはコメントを破棄します。コメントはLispシステム内でプログラムを表すLispオブジェクトの一部にはなりません。

#@count’構成は、次のcount個の文字をスキップします。これはプログラムにより生成されたバイナリーデータを含むコメントにたいして有用です。Emacs Lisp倍とコンパイラーは、出力ファイルにこれを使用します(Byte Compilationを参照してください)。しかしソースファイル用ではありません。

コメントのフォーマットにたいする慣例は、Tips on Writing Commentsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 Programming Types

Emacs Lispには2種類の一般的な型があります。1つはLispプログラミングに関わるもので、もう1つは編集に関わるものです。前者はさまざまな形で多くのLisp実装に存在します。後者はEmacs Lispに固有です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.1 Integer Type

整数の値の範囲はマシンに依存します、最小のレンジは-536,870,912から536,870,911(30ビットでは -2**29 から 2**29 - 1) ですが、多くのマシンはこれより広い範囲を提供します。Emacs Lispの数学関数は整数のオーバーフローをチェックしません。したがってEmacsのh整数が30ビットの場合、(1+ 536870911)は-536,870,912になります。

整数にたいする入力構文は、(10を基数とする)数字のシーケンスで、オプションで先頭に符号、最後にピリオドがつきます。Lispインタープリターにより生成されるプリント表記には、先頭の ‘+’や、最後の‘.’はありません。

-1               ; 整数の-1.
1                ; 整数の1.
1.               ; これも整数の1.
+1               ; これも整数の1.

特別な例外として、数字シーケンスが有効なオブジェクトとしては大きすぎる、または小さすぎる整数を指定する場合、Lispリーダーはそれを浮動小数点数(Floating-Point Typeを参照してください)として読み取ります。たとえば、Emacsの整数が30ビットの場合、536870912は浮動小数点数の536870912.0として読み取られます。

詳細は、Numbersを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.2 Floating-Point Type

浮動小数点数は、コンピューターにおける科学表記に相当するものです。浮動小数点数を10の指数をともなう有理数として考えることができます。正確な有効桁数と可能な指数は、マシン固有です。Emacsは値の保存にCデータ型のdoubleを使用し、内部的には10の指数ではなく、2の指数として記録します。

浮動小数点数のプリント表現には、(後に最低1つの数字をともなう)小数点と、指数のどちらか一方、または両方が必要です。たとえば‘1500.0’、‘+15e2’、‘15.0e+2’、‘+1500000e-3’、‘.15e4’は、いずれも浮動小数点数の1500を記述し、これらはすべて等価です。

詳細は、Numbersを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3 Character Type

Emacs Lispでの文字(character)は、整数以外の何者でもありません。他の言い方をすると、文字は文字コードで表現されます。たとえば文字Aは、整数の65として表現されます。

プログラムで文字を個別に使用するのは稀であり、文字のシーケンスとして構成される文字列(strings)として扱われるのがより一般的です。String Typeを参照してください。

文字列やバッファーの中の文字は、現在のところ0から4194303の範囲 — つまり22ビットに制限されています(Character Codesを参照してください)。0から127のコードはASCIIコードで、残りは非ASCIIです(Non-ASCII Charactersを参照してください)。キーボード入力を表す文字は、Control、Meta、Shiftなどの修飾キーをエンコードするために、より広い範囲をもちます。

メッセージのために、文字にたいして人間が読むことができるテキストによる説明を生成する特別な関数が存在します。Describing Characters for Help Messagesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3.1 Basic Char Syntax

文字は実際には整数なので、文字のプリント表現は10進数です。文字にたいする入力構文も利用可能ですが、Lispプログラムでこの方法により文字を記述するのは、明解なプログラミングではありません。文字にたいしては、Emacs Lispが提供する、特別な入力構文を常に使用するべきです。これらの構文フォーマットはクエスチョンマークで開始されます。

英数字にたいする通常の入力構文は、クエスチョンマークと、その後にその文字を記述します。したがって文字Aにたいしては‘?A’、文字Bにたいしては‘?B’、文字aにたいしては‘?a’となります。

たとえば:

?Q ⇒ 81     ?q ⇒ 113

句読点文字にも同じ構文を使用できますが、Lispコードを編集するためのEmacsコマンドが混乱しないように、‘\’を追加するのがよい場合がしばしばあります。たとえば開きカッコを記述するために‘?\(’と記述します。その文字が‘\’の場合、それをクォートするために、‘?\\’のように2つ目の‘\’を使用しなければなりません

control-g、backspace、tab、newline、vertical tab、formfeed、space、return、del、escapeはそれぞれ‘?\a’、‘?\b’、‘?\t’、‘?\n’、‘?\v’、‘?\f’、‘?\s’、‘?\r’、‘?\d’、‘?\e’と表すことができます(後にダッシュのついた‘?\s’は違う意味をもちます — これは後続の文字にたいして“super”の修飾を適用します)。したがって、

?\a ⇒ 7                 ; control-g, C-g
?\b ⇒ 8                 ; backspace, BS, C-h
?\t ⇒ 9                 ; tab, TAB, C-i
?\n ⇒ 10                ; newline, C-j
?\v ⇒ 11                ; vertical tab, C-k
?\f ⇒ 12                ; formfeed character, C-l
?\r ⇒ 13                ; carriage return, RET, C-m
?\e ⇒ 27                ; escape character, ESC, C-[
?\s ⇒ 32                ; space character, SPC
?\\ ⇒ 92                ; backslash character, \
?\d ⇒ 127               ; delete character, DEL

バックスラッシュが“エスケープ文字(escape character)”の役割を果たすので、これらのバックスラッシュで始まるシーケンスはエスケープシーケンス(escape sequences)とも呼ばれます。この用語法は、文字ESCとは関係ありません。‘\s’は文字定数としての使用を意図しており、文字定数の内部では、単にスペースを記述します。

エスケープという特別な意味を与えずに、任意の文字の前にバックスラッシュの使用することは許されており、害もありませんしたがって‘?\+’は‘?+’と等価です。ほとんどの文字の前にバックスラッシュを追加することに理由はありません。しかし、Lispコードを編集するEmacsコマンドが混乱するのを避けるために、文字‘()\|;'`"#.,’の前にはバックスラッシュを追加するべきです。space、tab、newline、formfeedのような空白文字の前にもバックスラッシュを追加できます。しかし、tabやspaceのような実際の空白文字のかわりに、‘\t’や‘\s’のような可読性のあるエスケープシーケンスを使用するほうが明解です(スペースを後にともなうバックスラッシュを記述する場合、後続のテキストと区別するために、文字定数の後に余分なスペースを記述するべきです)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3.2 General Escape Syntax

特に重要なコントロール文字にたいする特別なエスケープシーケンスに加えて、Emacsは非ASCIIテキスト文字の指定に使用できる、何種類かのエスケープ構文を提供します。

最初に、文字をUnicodeの値で指定することができます。?\unnnnはUnicodeのコードポイント‘U+nnnn’の文字を表します。ここでnnnnは、(慣例により)正確に4桁の16進数です。バックスラッシュは、後続の文字がエスケープシーケンスを形成することを示し、‘u’はUnicodeエスケープシーケンスを指定します。

U+ffffより大きなコードポイントをもつUnicode文字を指定するために、若干異なる構文が存在します。?\U00nnnnnnはコードポイント‘U+nnnnnn’の文字を表します。ここでnnnnnnは6桁の16進数です。Unicode Standardは‘U+10ffff’までのコードポイントだけを定義するので、これより大きいコードポイントを指定すると、Emacsはエラーをシグナルします。

次に、文字を16進の文字コードで指定できます。16進エスケープシーケンスは、バックスラッシュ、‘x’、および16進の文字コードにより構成されます。したがって‘?\x41’は文字A、‘?\x1’は文字C-a?\xe0は grave accentつきの文字‘a’を表します。 任意の数の16進数を使用できるので、この方法により任意の文字コードを表すことができます。

最後に、8進の文字コードにより文字を指定できます。8進エスケープシーケンスは、3桁までの8進数字をともなうバックスラッシュにより形成されます。したがって‘?\101’は文字A、‘?\001’は文字C-a?\002は文字C-bを表します。この方法で指定できるのは、8進コード777までの文字だけです。

これらのエスケープシーケンスは、文字列内でも使用されます。Non-ASCII Characters in Stringsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3.3 Control-Character Syntax

他の入力構文を使用してコントロール文字を表すことができます。これは後にバックスラッシュ、カレット、対応する非コントロール文字(大文字か小文字)をともなうクエスチョンマークから構成されます。たとえば‘?\^I’と‘?\^i’はどちらも、値が9である文字C-iにたいする、有効な入力構文です。

^’のかわりに、‘C-’を使用することもできます。したがって‘?\C-i’は、‘?\^I’や‘?\^i’と等価です。

?\^I ⇒ 9     ?\C-I ⇒ 9

文字列やバッファーの中では、ASCIIのコントロール文字だけが許されますが、キーボード入力にたいしては‘C-’により任意の文字をコントロール文字にすることができます。これらの非ASCIIのコントロール文字にたいするコントロール文字には 非コントロール文字にたいするコードと同様に、2**26 ビットが含まれます。通常のテキスト端末には、非ASCIIコントロール文字を生成する方法がありませんが、Xおよび他のウィンドウシステムを使用することにより、簡単に生成することができます。

歴史的な理由により、EmacsはDEL文字を、?のコントロール文字として扱います:

?\^? ⇒ 127     ?\C-? ⇒ 127

結果として、Xでは有意な入力文字であるControl-?文字を、‘\C-’を使用して表現することは今のところできません。さまざまなLispファイルがこの方法によりDELを参照するため、これを変更するのは簡単ではありません。

コントロール文字の表現はファイルや文字列のなかで見ることができますが、わたしたちは‘^’構文を推奨します。キーボード入力にたいするコントロール文字に好ましいのは、‘C-’構文です。どちらを使用するかはプログラムの意味に影響しませんが、プログラムを読む人の理解を助けるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3.4 Meta-Character Syntax

メタ文字(meta character)とは、META修飾キーとともにタイプされた文字です。そのような文字を表す整数には 2**27 のビットがセットされています。基本的な文字コードの広い範囲を利用可能にするために、メタや他の修飾にたいして上位ビットを使用します。

文字列では、メタ文字を示すASCII文字に、 2**7 ビットが付加されます。したがって文字列に含めることができるメタ文字のコードは1から255の範囲となり、メタ文字は通常のASCII文字のメタ修飾されたバージョンとなります。文字列内でのMETA処理の詳細については、Putting Keyboard Events in Stringsを参照してください。

メタ文字の入力構文には‘\M-’を使用します。たとえば‘?\M-A’はM-Aを意味します。8進文字コード(以下参照)や、‘\C-’、その他の文字にたいする他の構文とともに‘\M-’を使用できます。したがって、M-Aは‘?\M-A’や‘?\M-\101’と記述できます。同様に、C-M-bは‘?\M-\C-b’、‘?\C-\M-b’、‘?\M-\002’と記述することができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.3.5 Other Character Modifier Bits

グラフィック文字(graphic character)の大文字小文字は、文字コードで示されます。たとえばASCIIでは、文字‘a’と文字‘A’は区別されます。しかしASCIIにはコントロール文字が大文字なのか小文字なのかを表現する方法がありません。コントロール文字がタイプされたときシフトキーが使用されたかを示すために、Emacsは 2**25 のビットを使用します。この区別は、X端末や、他の特別な端末を使用しているときだけ可能です。通常のテキスト端末は、これらの違いを報告しません。シフトをあらわすビットのためのLisp構文は‘\S-’です。したがって‘?\C-\S-o’や‘?\C-\S-O’は、shifted-control-o文字を表します。

Xウィンドウシステムは文字にセットできる、他に3つ修飾ビット — hypersuperaltを定義します。これらのビットにたいする構文は、‘\H-’、‘\s-’、‘\A-’です(これらのプレフィクスでは、大文字小文字は意味があります)。したがって‘?\H-\M-\A-x’はAlt-Hyper-Meta-xを表します(‘-’が後にない‘\s’は、スペース文字を表すことに注意してください)。 数値的には、ビット値2**22はalt、2**23はsuper、2**24はhyperです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.4 Symbol Type

GNU Emacs Lispでのシンボル(symbol)とは、名前をもつオブジェクトです。シンボル名は、そのシンボルのプリント表現としての役割があります。Lispの通常の使用では、1つのobarray(Creating and Interning Symbolsを参照してください)により、シンボル名は一意です — 2つのシンボルが同じ名前をもつことはありません。

シンボルは、変数、関数名としての役割や、プロパティーリストを保持する役割をもつことができます。他のすべてのLispオブジェクトから区別するためだけの役割をもつ場合もあり、データ構造内にそのようなシンボルが存在することは、確実に認識されるでしょう。与えられたコンテキストにおいて、通常はこれらのうちの1つの使用だけが意図されます。しかし3つすべての方法で、1つのシンボルを独立して使用することもできます。

名前がコロン(‘:’)で開始されるシンボルは、キーワードシンボル(keyword symbol)と呼ばれます。これらのシンボルは自動的に定数として振る舞い、通常は未知のシンボルと、いくつかの特定の候補を比較することだけに使用されます。Variables that Never Changeを参照してください。

シンボル名にはどんな文字でも含めることができます。ほとんどのシンボル名は英字、数字、‘-+=*/’などの句読点文字で記述されます。このような名前には、特別な句読点文字は必要ありません。名前が数字のように見えない限りは、名前にはどのような文字も使用できます(名前が数字のように見える場合は、名前の先頭に‘\’を記述して、強制的にシンボルとして解釈させます)。文字‘_~!@$%^&:<>{}?’はあまり使用されませんが、これらも特別な句読点文字を必要としません。他の文字も、バックスラッシュでエスケープすることにより、シンボル名に含めることができます。しかし、文字列内でのバックスラッシュの使用とは対照的に、シンボル名でのバックスラッシュは、バックスラッシュの後の1文字をエスケープするだけです。たとえば文字列内では、‘\t’はタブ文字を表します。しかしシンボル名の中では、‘\t’は英字‘t’をクォートするに過ぎません。 名前にタブ文字をもつシンボルを記述するには、(バックスラッシュを前置した)実際のタブを使用しなければなりません。しかし、そのようなことを行なうことは、めったにありません。

Common Lispに関する注意:Common Lispでは、明示的にエスケープされない限り、小文字は常に大文字に“フォールドされ(folded)”ます。Emacs Lispでは大文字と小文字は区別されます。

以下はシンボル名の例です。4番目の例の中の‘+’は、シンボルが数字として読み取られるのを防ぐために、エスケープされていることに注意してください。6番目の例では、名前の残りの部分により数字としては不正なので、エスケープの必要はありません。

foo                 ; foo’という名前のシンボル。
FOO                 ; foo’とは別の、‘FOO’という名前のシンボル。
1+                  ; 1+’という名前のシンボル
                    ;   (整数の‘+1’ではありません)。
\+1                 ; +1’という名前のシンボル
                    ;   (とても読みやすい名前とはいえません)。
\(*\ 1\ 2\)         ; (* 1 2)’という名前のシンボル(悪い名前)。
+-*/_~!@$%^&=:<>{}  ; +-*/_~!@$%^&=:<>{}’という名前のシンボル。
                    ;   これらの文字はエスケープする必要はありません。

シンボル名がプリント表現としての役割をもつというルールの例外として、‘##’があります。これは、名前が空文字列の、internされたシンボルのプリント表現です。さらに‘#:foo’は、internされていないfooという名前のシンボルにたいするプリント表現です(通常、Lispリーダーはすべてのシンボルをinternします。Creating and Interning Symbolsを参照してください)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.5 Sequence Types

シーケンス(sequence)とは、要素の順序セットを表現する、Lispオブジェクトです。Emacs Lispには、2種類のシーケンス — リスト(lists)配列(arrays)があります。

リストはもっとも一般的に使用されるシーケンスです。リストは任意の型の要素を保持でき、要素の追加・削除により簡単に長さを変更できます。リストについては、次のサブセクションを参照してください。

配列は固定長のシーケンスです。配列はさらに文字列(strings)、ベクター(vectors)、文字テーブル(char-tables)、ブールベクター(bool-vectors)に細分されます。ベクターは任意の型の要素を保持できますが、文字列の要素は文字でなければならず、ブールベクターの要素はtnilでなければなりません。文字テーブルはベクターと似ていますが、有効な文字によりインデックスづけされる点が異なります。文字列内の文字は、バッファー内の文字のようにテキストプロパティーをもつことができます(Text Propertiesを参照してください)。しかしベクターは、その要素が文字のときでも、テキストプロパティーをサポートしません。

リスト、文字列、およびその他の配列型も、重要な類似点を共有します。たとえば、それらはすべて長さlをもち、要素は0からl-1でインデックスづけされます。いくつかの関数はシーケンス関数と呼ばれ、これらは任意の種類のシーケンスを許容します。たとえば、関数lengthは、任意の種類のシーケンスの長さを報告します。Sequences, Arrays, and Vectorsを参照してください。

シーケンスは読み取りにより常に新たに作成されるので、同じシーケンスを2回読み取るのは、一般的に不可能です。シーケンスにたいする入力構文を2回読み取った場合、内容が等しい2つのシーケンスを得ます。これには1つ例外があります。空リスト()は、常に同じオブジェクトnilを表します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.6 Cons Cell and List Types

コンスセル(cons cell)は、CARスロット、CDRスロットと呼ばれる2つのスロットから構成されるオブジェクトです。各スロットは、任意のLispオブジェクトを保持できます。そのときCARスロットに保持されるオブジェクトが何であれ、わたしたちは“このコンスセルのCAR”のような言い方をします。これはCDRの場合も同様です。

リスト(list)は、コンスセルの連続するシリーズで、各コンスセルのCDRスロットは、次のコンスセル、または空リストを保持します。空リストは実際にはシンボルnilです。詳細については、Listsを参照してください。ほとんどのコンスセルはリストの一部として使用されるので、わたしたちはコンスセルにより構成される任意の構造を、リスト構造(list structure)という用語で参照します。

Cプログラマーにたいする注意: Lispのリストはコンスセルにより構築される、リンクリスト(linked list)として機能します。Lispではポインターは暗黙的なので、わたしたちはコンスセルのスロットが、値を“保持(hold)”するのか、それとも値を“指す(point)”のかを区別しません。

コンスセルはLispの中心なので、“コンスセルではないオブジェクト”にたいする単語もあります。これらのオブジェクトはアトム(atoms)と呼ばれます。

リストにたいする入力構文とプリント表現は等しく、それは左カッコ、任意の数の要素、右カコから構成されます。以下はリストの例です:

(A 2 "A")            ; 3要素のリスト。
()                   ; 要素がないリスト(空リスト)。
nil                  ; 要素がないリスト(空リスト)。
("A ()")             ; 1要素のリスト: 文字列"A ()"
(A ())               ; 2要素のリスト: Aと空リスト。
(A nil)              ; 同上
((A B C))            ; 1要素のリスト
                     ;   (この要素は、3要素のリスト)。

読み取りにおいては、カッコの内側は、リストの要素になります。つまり、コンスセルは各要素から作成されます。コンスセルのCARスロットは要素を保持し、CDRスロットはリスト内の次のコンスセル(このコンスセルはリスト内の次の要素を保持します)を参照します。最後のコンスセルのCDRスロットは、nilを保持するようにセットされます。

CARCDRという名称は、Lispの歴史に由来します。オリジナルのLisp実装はIBM 704コンピューターで実行されていました。ワードを2つの部分、つまり“address”と呼ばれる部分と、“decrement”と呼ばれる部分に分割していて、その際CARはaddress部から内容を取り出す命令で、CDRはdecrement部から内容を取り出す命令でした。対照的に“cons cells”は、これらを作成する関数consから命名されました。この関数は関数の目的、すなわちセルを作る(construction of cells)という目的から命名されました。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.6.1 Drawing Lists as Box Diagrams

コンスセルを表現するドミノのような1対のボックスによる図により、リストを説明することができます(Lispリーダーがこのような図を読み取ることはできません。人間およびコンピューターが理解できるテキスト表記と異なり、ボックスの図は人間だけが理解できます)。この図は3要素のリスト(rose violet buttercup)を表したものです:

    --- ---      --- ---      --- ---
   |   |   |--> |   |   |--> |   |   |--> nil
    --- ---      --- ---      --- ---
     |            |            |
     |            |            |
      --> rose     --> violet   --> buttercup

この図では、ボックスは任意のLispオブジェクトへの参照を保持できるスロットを表します。ボックスのペアはコンスセルを表します。矢印はLispオブジェクト(アトム、または他のコンスセル)への参照を表します。

この例では、1番目のボックスは1番目のコンスセルで、それのCARrose(シンボル)を参照または“保持(holds)”します。2番目のボックスは1番目のコンスセルのCDRを保持し、次のボックスペア、すなわち2番目のコンスセルを参照します。2番目のコンスセルのCARvioletで、CDRは3番目のコンスセルです。(最後の)3番目のコンスセルのCDRは、nilです。

同じリスト(rose violet buttercup)を、違うやり方で描いた別の図で表してみましょう:

 ---------------       ----------------       -------------------
| car   | cdr   |     | car    | cdr   |     | car       | cdr   |
| rose  |   o-------->| violet |   o-------->| buttercup |  nil  |
|       |       |     |        |       |     |           |       |
 ---------------       ----------------       -------------------

要素がないリストは空リスト(empty list)で、これはシンボルnilと同じです。別の言い方をすると、nilはシンボルであり、リストでもあります。

以下は、リスト(A ())、または等価な(A nil)をボックスと矢印で描いたものです:

    --- ---      --- ---
   |   |   |--> |   |   |--> nil
    --- ---      --- ---
     |            |
     |            |
      --> A        --> nil

以下はもっと複雑な例です。これは、1番目の要素が2等疎のリスとである、3要素のリスト((pine needles) oak maple)を表します:

    --- ---      --- ---      --- ---
   |   |   |--> |   |   |--> |   |   |--> nil
    --- ---      --- ---      --- ---
     |            |            |
     |            |            |
     |             --> oak      --> maple
     |
     |     --- ---      --- ---
      --> |   |   |--> |   |   |--> nil
           --- ---      --- ---
            |            |
            |            |
             --> pine     --> needles

同じリストを2番目のボックス表記で表すと、以下のようになります:

 --------------       --------------       --------------
| car   | cdr  |     | car   | cdr  |     | car   | cdr  |
|   o   |   o------->| oak   |   o------->| maple |  nil |
|   |   |      |     |       |      |     |       |      |
 -- | ---------       --------------       --------------
    |
    |
    |        --------------       ----------------
    |       | car   | cdr  |     | car     | cdr  |
     ------>| pine  |   o------->| needles |  nil |
            |       |      |     |         |      |
             --------------       ----------------

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.6.2 Dotted Pair Notation

ドットペア表記(dotted pair notation)CARCDRが明示的に表されたコンスセルにたいする、一般的な構文です。この構文では、(a . b)は、CARがオブジェクトaで、CDRがオブジェクトbという意味になります。CDRがリスとである必要がないので、ドットペア表記は、より一般的なリスト構文です。しかしキスと構文が機能するでような場合には、より扱いにくくなります。ドットペア表記では、リスト‘(1 2 3)’は、‘(1 . (2 . (3 . nil)))’と記述されます。nilで終端されたリストにたいしては、どちらの表記法も使用できますが、リスト表記の方が、通常は明解で便利です。リストをプリントする場合、コンスセルのCDRがリスとでないときだけ、ドットペア表記が使用されます。

以下はボックスを使用してドットペア表記を表した例です。この例はペア(rose . violet)を表します。

    --- ---
   |   |   |--> violet
    --- ---
     |
     |
      --> rose

最後のCDRが非nilのコンスセルのチェーンを表すために、ドットペア表記とリスト表記を組み合わせることができます。リストの最後の要素の後にドットを記述して、その後に最後のコンスセルのCDRを記述します。たとえば、(rose violet . buttercup)は、(rose . (violet . buttercup))と等価です。オブジェクトは以下のようになります:

    --- ---      --- ---
   |   |   |--> |   |   |--> buttercup
    --- ---      --- ---
     |            |
     |            |
      --> rose     --> violet

構文(rose . violet . buttercup)は無効です。なぜならこれが意味することは何もないからです。何かあるにしても、violetのためにCDRがすでに使用されているコンスセルのCDRbuttercupを置く、ということになります。

リスト(rose violet)(rose . (violet))と等価であり、以下のようになります:

    --- ---      --- ---
   |   |   |--> |   |   |--> nil
    --- ---      --- ---
     |            |
     |            |
      --> rose     --> violet

同様に3要素のリスト(rose violet buttercup)は、(rose . (violet . (buttercup)))と等価です。 これは以下のようになります:

    --- ---      --- ---      --- ---
   |   |   |--> |   |   |--> |   |   |--> nil
    --- ---      --- ---      --- ---
     |            |            |
     |            |            |
      --> rose     --> violet   --> buttercup

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.6.3 Association List Type

連想リスト(association list)またはalistは、要素がコンスセルであるように特別に構成されたリストです。各要素においては、CARキー(key)で、CDR連想値(associated value)であると考えます(連想値がCDRCARに保存される場合もあります)。リストの先頭に連想値を追加したり削除するのが簡単なので、連想リストはスタック(stack)にしばしば使用されます。

たとえば、

(setq alist-of-colors
      '((rose . red) (lily . white) (buttercup . yellow)))

これは変数alist-of-colorsに3葉疎のalistをセットします。最初の要素では、roseがキーで、redが値になります。

alistと、alistに関数についての詳細な説明は、Association Listsを参照してください。テーブルを照合する、(多くのキーの操作を、より速く行なう)他の手段については、Hash Tablesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.7 Array Type

配列(array)は、他のLispオブジェクトを保持または参照する、任意の数のスロットから構成され、メモリーの連続ブロックに配列されます。配列の任意の要素へのアクセス時間は、大体同じです。対照的に、リストの要素にたいするアクセスは、リスト内でのその要素の位置に比例した時間を要します(リストの最後の要素にアクセスするには、リストの最初の要素にアクセスするより、長い時間を要します)。

Emacsは文字列(strings)、ベクター(vectors)、ブールベクター(bool-vectors)、文字テーブル(char-tables)という、4種の配列を定義します。

文字列は文字の配列で、ベクターは任意のオブジェクトの配列です。ブールベクターはtnilだけを保持できます。この種の配列は、もっとも大きい整数までの、任意の長さをもつことができます。文字テーブルは、任意の有効な文字コードによりインデックスづけされる疎な配列で、任意のオブジェクトを保持することができます。

配列の最初の要素はインデックス0、2番目の要素はインデックス1、...となります。これは0基準zero-originのインデックスづけと呼ばれます。たとえば、4要素の配列は、インデックス0、1、2、3をもちます。利用できる最大のインデックス値は、配列の長さより1小さくなります。1度配列が作成されると、長さは固定されます。

Emacs Lispのすべての配列は、1次元です(他のほとんどのプログラミング言語は多次元配列をサポートしますが、これらは必須ではありません。ネストされた1次元配列により同じ効果を得ることができます)。各種の配列のは、独自の入力構文をもちます。詳細は以降のセクションを参照してください。

配列型はシーケンス型のサブセットであり、文字列型、ベクター型、ブールベクター型、文字テーブル型が含まれます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.8 String Type

文字列(string)とは、文字の配列です。Emacsがテキストエディターであることから予想できるように、文字列は、たとえばLispシンボルの名前、ユーザーへのメッセージ、バッファーから抽出されたテキストの表現など、多くの目的のために使用されます。Lispの文字列は定数です。文字列を評価すると、それと同じ文字列がreturnされます。

文字列を操作する関数については、Strings and Charactersを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.8.1 Syntax for Strings

文字列にたいする入力構文は、"like this"のように、ダブルクォート、任意個の文字、もう1つのダブルクォートから構成されます。文字列内にダブルクォートを含める場合は、それの前にバックスラッシュを記述します。したがって、"\""は1つのダブルクォート文字だけを含む文字列です。同様に、バックスラッシュを含める場合は、"this \\ is a single embedded backslash"のように、それの前にもう1つのバックスラッシュを記述します。

文字列にたいする入力構文では、改行(newline)は特別ではありません。ダブルクォートの間に改行を記述すれば、その改行は文字列内の文字となります。しかしエスケープされた改行 — 前に‘\’をともなう改行 —は文字列の一部とはなりません。同様に、エスケープされたスペース‘\  も無視されます。

"It is useful to include newlines
in documentation strings,
but the newline is \
ignored if escaped."
     ⇒ "It is useful to include newlines
in documentation strings,
but the newline is ignored if escaped."

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.8.2 Non-ASCII Characters in Strings

Emacdの文字列内の非ASCII文字にたいしては、2つのテキスト表現 — マルチバイト(multibyte)とユニバイト(unibyte)があります(Text Representationsを参照してください)。大まかに言うと、ユニバイト文字列にはraw(生)バイトが保存され、マルチバイト文字列には人間が読めるテキストが保存されます。ユニバイト文字列内の各文字はバイトであり、値は0から255となります。対照的に、マルチバイト文字列内の各文字は、0から4194303の値をもつかもしれません(Character Typeを参照してください)。両方とも、127より上の文字は非ASCIIです。

文字をリテラルとして記述することにより、文字列に非ASCII文字を含めることができます。マルチバイトのバッファーや文字列、あるいはマルチバイトとしてvisitされたファイル等の、マルチバイトのソースから文字列定数を読み込む場合、Emacsは非ASCII文字をマルチバイト文字として読み取り、その文字列を自動的にマルチバイト文字列にします。ユニバイトのソースから文字列定数を読み込む場合、Emacsは非ASCII文字をユニバイト文字として読み取り、その文字列を湯にバイト文字列にします。

マルチバイト文字列内にリテラルとして文字を記述するかわりに、エスケープシーケンスを使用して文字コードとして記述できます。エスケープシーケンスについての詳細は、General Escape Syntaxを参照してください。

文字列定数内でUnicodeスタイルのエスケープシーケンス‘\uNNNN’または‘\U00NNNNNN’を使用する場合、(たとえASCII文字の場合でも)Emacsは自動的に文字列をマルチバイトとみなします。

文字列定数内で、16進エスケープシーケンス(‘\xn’)、および8進エスケープシーケンス(‘\n’)を使用することもできます。しかし注意してください: 文字列定数が16進または8進のエスケープシーケンスを含み、それらのエスケープシーケンスすべてがユニバイト文字(256より小)を指定していて、その文字列内に他にリテラルの非ASCII文字またはUnicodeスタイルのエスケープシーケンスが存在しない場合、Emacsは自動的に文字列をユニバイト文字列とみなします。つまり文字列内のすべての非ASCII文字は8ビットのrawバイトとみなされます。

16進および8進のエスケープシーケンスではエスケープされた文字コードは可変個の数字を含むかもしれないので、それに続く文字で、16進および8進として有効ではない最初の文字は、エスケープシーケンスを終了させます。文字列内の次の文字が16進または8進として解釈できる文字の場合は、‘\  (バックスラッシュとスペース)を記述して、エスケープシーケンスを終了できます。たとえば‘\xe0\ はgrave accentつきの‘a’という、1文字を表します。文字列内の‘\  は、バックスラッシュー改行と同様です。これは文字列内の文字とはなりませんが、先行する16進エスケープを終了します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.8.3 Nonprinting Characters in Strings

リテラル文字と同様に、文字列定数内でバックスラッシュによるエスケープシーケンスを使用できます(ただし文字定数を開始するクエスチョンマークは使用しません)。たとえば、非プリント文字のタブとC-aを含む文字列は、"\t, \C-a"のように、それらの間にカンマとスペースを記述します。文字にたいする入力構文の説明は、Character Typeを参照してください。

しかし、バックスラッシュによるエスケープシーケンスとともに記述できるすべての文字が、文字列内で有効というわけではありません。文字列が保持できるコントロール文字は、ASCIIコントロール文字だけです。ASCIIコントロール文字では、文字列の大文字小文字は区別されません。

正確に言うと、文字列はメタ文字を保持できません。しかし文字列がキーシーケンスとして使用される場合、文字列内でメタで修飾されたASCII文字を表現するための方法を提供する、特別な慣習があります。文字列定数内でメタ文字を示すために‘\M-’構文を使用した場合、これは文字列内の文字の 2**7 のビットをセットします。その文字列がdefine-keyまたはlookup-keyで使用される場合、この数字コードは等価なメタ文字に変換されます。Character Typeを参照してください。

文字列はhyper、super、altで修飾された文字を保持できません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.8.4 Text Properties in Strings

文字列は、その文字自身に加えて、文字のプロパティーも保持することができます。これにより、特別なことをしなくても、文字列とバッファーとの間でテキストをコピーするプログラムが、テキストプロパティーをコピーすることが可能になります。テキストプロパティーが何を意味するかについての説明は、Text Propertiesを参照してください。テキストプロパティーをもつ文字列は、特別な入力構文とプリント構文を使用します。

#("characters" property-data...)

ここでproperty-dataは3個でグループ化された、0個以上の要素から構成されます:

beg end plist

要素begおよびendは整数で、文字列内のインデックスの範囲を指定します。plistはその範囲にたいするプロパティーリストです。たとえば、

#("foo bar" 0 3 (face bold) 3 4 nil 4 7 (face italic))

これはテキスト内容が‘foo bar’で、最初の3文字はfaceプロパティーに値boldをもち、最後の3文字はfaceプロパティーに値italicをもつことを表します。(4番目の文字にはテキストプロパティーはないので、プロパティーリストはnilです。実際には、範囲の中の指定されていない文字はデフォルトではプロパティーをもたないので、範囲のプロパティーリストをnilと指定する必要ありません)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.9 Vector Type

ベクター(vector)は、任意の型の要素からなる1次元の配列です。ベクター内の任意の要素へのアクセスに要す時間は、一定です(リストの場合、要素へのアクセスに要す時間は、リストの先頭からその要素までの距離に比例します)。

ベクターのプリント表現は、左角カッコ(left square bracket)、要素、右角カッコ(right square bracket)から構成されます。これは入力構文でもあります。数字や文字列と同様に、ベクターは評価において定数と判断されます。

[1 "two" (three)]      ; 3要素のベクター。
     ⇒ [1 "two" (three)]

ベクターに作用する関数については、Vectorsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.10 Char-Table Type

文字テーブル(char-table)は、任意の型の要素をもつ1次元の配列で、文字コードによりインデックスづけされます。文字テーブルは、文字コードに情報を割り当てることを必要とする多くの処理を簡単にするための、特別な追加の機能をもちます — たとえば、文字テーブルは、継承するための親、デフォルト値、特別な目的のために使用する少数の余分なスロットをもつことができます。文字テーブルは、文字セット全体にたいして1つの値を指定することもできます。

文字テーブルのプリント表現はベクターと似ていますが、最初に余分な‘#^’があります1

文字テーブルを操作する特別な関数については、Char-Tablesを参照してください。文字テーブルの使用には以下が含まれます:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.11 Bool-Vector Type

ブールベクター(bool-vector)は、要素がtnilでなければならない、1次元の配列です。

ブールベクターのプリント表現は文字列と似ていますが、後に長さを記述した‘#&’で始まります。これに続く文字列定数は、ビットマップとして実際に内容を指定するブールベクターです — 文字列定数内のそれぞれの“文字”は8ビットを含み、これはブールベクターの次の8要素を指定します(1はt、0はnilです)。文字の最下位ビットブールベクターの最下位のインデックスに対応します。

(make-bool-vector 3 t)
     ⇒ #&3"^G"
(make-bool-vector 3 nil)
     ⇒ #&3"^@"

C-g’の2進コードは111、‘C-@’はコード0の文字なので、この結果は道理にかなっています。

長さが8の倍数でない場合、プリント表現には余分な要素が表示されますが、これらの余分な要素に意味はありません。たとえば以下の例では、最初の3ビットだけが使用されるので、2つのブールベクターは等価です:

(equal #&3"\377" #&3"\007")
     ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.12 Hash Table Type

ハッシュテーブルは非常に高速な照合テーブルの一種で、キーを対応する値にマップするalistと似ていますが、より高速です。ハッシュテーブルのプリント表現、以下のようにハッシュテーブルのプロパティーと内容を指定します:

(make-hash-table)
     ⇒ #s(hash-table size 65 test eql rehash-size 1.5
                             rehash-threshold 0.8 data ())

ハッシュテーブルについての詳細な情報は、Hash Tablesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.13 Function Type

他のプログラミング言語の関数と同様に、Lisp関数は実行可能なコードです。他の言語とは異なり、Lispの関数はLispオブジェクトでもあります。Lispのコンパイルされていない関数はラムダ式 — つまり1番目の要素がシンボルlambdaであるリストです(Lambda Expressionsを参照してください)。

ほとんどのプログラミング言語では、名前のないの関数はありません。Lispでは、関数に本質的な名前はありません。名前がなくても、ラムダ式を関数として呼び出すことができます。これを強調するために、わたしたちはこれを無名関数(anonymous function)とも呼びます(Anonymous Functionsを参照してください)。Lispの名前つき関数は、関数セルに有効な関数がセットされた単なるシンボルです(Defining Functionsを参照してください)。

ほとんどの場合、関数はLispプログラム内のLisp式に名前が記述されたところで呼び出されます。しかし、実行時に関数オブジェクトを構築または取得してから、基本関数funcallおよびapplyにより呼び出すことができます。Calling Functionsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.14 Macro Type

Lispマクロ(Lisp macro)は。Lisp言語を拡張する、ユーザー定義の構成です。これはオブジェクトとしてではなく関数のように表現されますが、引数の渡し方の意味が異なります。Lispマクロの形式はリストです。これは、最初の要素がmacroで、(lambdaシンボルを含む)CDRがLisp関数オブジェクトであるようなリストです。

Lispマクロオブジェクトは通常、ビルトインのdefmacro関数で定義されますが、macroで始まる任意のリストも、Emacsにとってはマクロです。マクロを記述する方法の説明は、Macrosを参照してください。

警告: Lispマクロとキーボードマクロ(Keyboard Macrosを参照してください)は、完全に別物です。修飾なしで“マクロ”という単語を使用したときは、キーボードマクロではなく、Lispマクロのことを指します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.15 Primitive Function Type

基本関数(primitive function)とは、Cプログラミング言語で記述された、Lispから呼び出せる関数です。基本関数はsubrsビルと陰関数(built-in functions)とも呼ばれます(単語“subr”は、“サブルーチン(subroutine)”が由来です)。ほとんどの基本関数、呼び出されたとき、すべての引数を評価します。すべての引数を評価しない基本関数は、スペシャルフォーム(special form)と呼ばれます(Special Formsを参照してください)。

呼び出す側からすれば、その関数が基本関数かどうかは、問題になりません。しかし、基本関数をLispで記述された関数で再定義した場合は、問題になります。理由は、その基本関数がCコードから直接呼び出されているかもしれないからです。Lispから再定義した関数を呼び出すと、これは新しい定義を使用するでしょうが、Cコードから呼び出すと、ビルトインの定義が使用されるでしょう。したがって、基本関数の再定義はしないでください

関数(function)という用語により、LispやCで記述された、すべてのEmacs関数を参照します。Lispで記述された関数についての情報は、Function Typeを参照してください。

基本関数に入力構文はなく、サブルーチン名とともにハッシュ表記でプリントします。

(symbol-function 'car)          ; そのシンボルの関数セルに
                                ;     アクセスします。
     ⇒ #<subr car>
(subrp (symbol-function 'car))  ; これは基本関数か?
     ⇒ t                ;    イェース。

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.16 Byte-Code Function Type

バイトコード関数オブジェクト(byte-code function objects)は、Lispコードをバイトコンパイルすることにより生成されます(Byte Compilationを参照してください)。内部的には、バイトコード関数オブジェクトは、ベクターによく似ています。しかしバイトコード関数オブジェクトが関数呼び出しのように見える場合、評価プロセスにより、このデータ型は特別に処理されます。Byte-Code Function Objectsを参照してください。

バイトコード関数オブジェクトのプリント表現と入力構文は、ベクターのものと似ていますが、開き角カッコ‘[’の前に‘#’があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.17 Autoload Type

autoloadオブジェクト(autoload object)は、最初の要素がシンボルautoloadのリストです。これはシンボルの関数定義として保存され、実際の定義にたいする代替としての役割をもちます。autoloadオブジェクトは、必要な時にロードされるLispコードファイルのなかで、実際の定義を見つけることができることを宣言します。これにはファイル名と、加えて実際の定義についての他のいくつかの情報が含まれます。

ファイルがロードされた後、そのシンボルは、autoloadオブジェクトではない、新しい関数定義をもつはずです。新しい定義は、最初からそこにあったかのように呼び出されます。ユーザーの観点からは、関数呼び出しは期待された動作、つまりロードされたファイル内の関数定義を使用します。

autoloadオブジェクトは通常、シンボルの関数セルにオブジェクトを保存する、関数autoloadにより作成されます。詳細は、Autoloadを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 Editing Types

前のセクションの型は一般的なプログラミングの目的のために使用され、これらのほとんどは、ほとんどのLisp方言で一般的です。Emacs Lispは、編集に関する目的のために、いくつかの追加のデータ型を提供します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.1 Buffer Type

バッファー(buffer)とは、編集されるテキストを保持するオブジェクトです(Buffersを参照してください)。ほとんどのバッファーはディスクファイル(Filesを参照してください)の内容を保持するので、それらは編集できますが、他の目的のために使用されるものもいくつかあります。ほとんどのバッファーは、ユーザーにより閲覧されることも意図しているので、いつかはウィンドウ内(Windowsを参照してください)に表示されます。しかしバッファーはウィンドウに表示される必要はありません。バッファーはそれぞれ、ポイント(point)と呼ばれる位置指定をもちます(Positionsを参照してください)。ほとんどの編集コマンドは、カレントバッファー内のポイントに隣接する内容を処理します。常に1つのバッファーがカレントバッファー(current buffer)です。

バッファーの内容は文字列によく似ていますが、バッファーはEmacs Lispの文字列と同じようには使用されず、利用可能な操作は異なります。文字列にテキストを“挿入”するためには、部分文字列の結合が必要で、結果は完全に新しい文字列オブジェクトなのに比べて、バッファーでは既存のバッファーに効率的にテキストを挿入して、バッファーの内容を変更できます。

標準的なEmacs関数の多くは、カレントバッファー内の文字を操作したりテストするためのものです。このマニュアルには、これらの関数の説明のために、1つのチャプターをあてています(Textを参照してください)。

他のデータ構造のいくつかは、各バッファーに関連付けられています:

ローカルキーマップと変数リストは、具ローマルナバインディングや値を個別にオーバーライドするためのエントリーを含みます。これらは、実際にプログラムを変更することなく、異なるバッファーでのプログラムの振る舞いをカスタマイズするために使用されます。

バッファーはインダイレクト(indirect: 間接) — つまり他のバッファーとテキストを共有するが、それぞれ別に表示する — かもしれません。Indirect Buffersを参照してください。

バッファーに入力構文はありません。バッファーはバッファー名を含むハッシュ表記でプリントされます。

(current-buffer)
     ⇒ #<buffer objects.texi>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.2 Marker Type

マーカー(marker)は、特定のバッファー内の位置を表します。したがってマーカーには2つの内容 — 1つはバッファー、もう1つは位置 — をもちます。バッファーのテキストの変更では、マーカーが常にバッファー内の同じ2つの文字の間に位置することを確実にするために、必要に応じて自動的に位置の値が再配置されます。

マーカーは入力構文をもちません。マーカーは、カレントの文字位置と、そのバッファー名を与える、ハッシュ表記でプリントされます。

(point-marker)
     ⇒ #<marker at 10779 in objects.texi>

マーカーのテスト、作成、コピー、移動の方法についての情報は、Markersを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.3 Window Type

ウィンドウ(window)はEmacsがバッファーを表示するために使用する端末スクリーンの部分を記述します。すべてのウィンドウは関連付けられた1つのバッファーをもち、バッファーの内容はそのウィンドウに表示されます。対照的に、あるバッファーは、1つのウィンドウに表示されるか、ウィンドウに表示されないか、それとも複数のウィンドウに表示されるかもしれません。

同時に複数のウィンドウが存在するかもしれませんが、常に1つのウィンドウが選択されたウィンドウ(selected window)になります。Emacsがコマンドにたいして準備できているときに、(通常は)カーソルが表示されるウィンドウが、選択されたウィンドウです。選択されたウィンドウは通常、カレントバッファーを表示しますが、これは必須ではありません。

スクリーン上でウィンドウはフレームにグループ化されます。各ウィンドウは、ただ1つだけのフレームに属します。Frame Typeを参照してください。

ウィンドウは入力構文をもちません。ウィンドウは、ウィンドウ番号、表示されているバッファー名を与える、ハッシュ表記でプリントされます。与えられたウィンドウに表示されるバッファーは頻繁に変更されるかもしれないので、一意にウィンドウを識別するためにウィンドウ番号が存在します。

(selected-window)
     ⇒ #<window 1 on objects.texi>

ウィンドウに作用する関数の説明は、Windowsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.4 Frame Type

フレーム(frame)とは、1つ以上のEmacsウィンドウを含むスクリーン領域です。スクリーン領域を参照するためにEmacsが使用するLispオブジェクトを指す場合も、“フレーム”という用語を使用します。

フレームは入力構文をもちません。フレームはフレームのタイトル、(フレームを一意に識別するのに便利な)メモリー内のアドレスを与えるハッシュ表記でプリントされます。

(selected-frame)
     ⇒ #<frame emacs@psilocin.gnu.org 0xdac80>

フレームに作用する関数の説明は、Framesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.5 Terminal Type

端末(terminal)は、1つ以上のEmacsフレーム(Frame Typeを参照してください)を表示する能力があるデバイスです。

端末は入力構文をもちません。端末は、その端末の順序番号、TTYデバイスファイル名を与える、ハッシュ表記でプリントされます。

(get-device-terminal nil)
     ⇒ #<terminal 1 on /dev/tty>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.6 Window Configuration Type

ウィンドウ構成(window configuration)は、フレーム内のウィンドウの位置、サイズ、内容についての情報を保持します。これにより後で同じウィンドウ配置を再作成できます。

ウィンドウ構成は入力構文をもちません。ウィンドウ構成のプリント表現は、‘#<window-configuration>’のようになります。ウィンドウ構成に関連するいくつかの関数の説明は、Window Configurationsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.7 Frame Configuration Type

フレーム構成(frame configuration)は、すべてのフレーム内のウィンドウの位置、サイズ、内容についての情報を保持します。これは基本型ではありません — 実際のところ、これはCARframe-configurationで、CDRがalistのリストです。各alist要素は、その要素のCARに示される1つのフレームを記述します。

フレーム構成に関連するいくつかの関数の説明は、Frame Configurationsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.8 Process Type

単語プロセス(process)は通常、実行中のプログラムを意味します。Emacs自身はこの種のプロセス内で実行されます。しかしEmacs Lispでは、プロセスとはEmacsプロセスにより作成されたサブプロセスを表す、Lispオブジェクトです。シェル、GDB、ftp、コンパイラーなどのプログラムは、Emacsのサブプロセスとして実行され、Emacsの能力を拡張します。さらに操作を行なうために、Emacsサブプロセスは、Emacsからテキスト入力を受け取り、テキスト出力をEmacsにreturnします。Emacsは、サブプロセスにシグナルを送ることもできます。

プロセスオブジェクトは入力構文をもちません。プロセスオブジェクトは、プロセス名を与えるハッシュ表記でプリントされます。

(process-list)
     ⇒ (#<process shell>)

プロセスの作成、削除、プロセスに関する情報のreturn、入力やシグナルの送信、出力の受信を行なう関数についての情報は、Processesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.9 Stream Type

ストリーム(stream)とは、文字のソースまたはシンクとして — つまり入力として文字を供給したり、出力として文字を受け入れるために使用できるオブジェクトです。多くの異なるタイプ — マーカー、バッファー、文字列、関数を、この方法で使用できます。ほとんどの場合、入力ストリーム(文字列ソース)は、キーボード、バッファー、ファイルから文字を受け取り、出力ストリーム(文字シンク)は文字を*Help*バッファーのようなバッファー、エコーエリアに文字を送ります。

オブジェクトnilは、他の意味に加えて、ストリームとして使用されることがあります。nilは変数standard-inputstandard-outputの値を表します。オブジェクトtも、入力としてミニバッファー(Minibuffersを参照してください)、出力としてエコーエリア(The Echo Areaを参照してください)の使用を指定するストリームになります。

ストリームは特別なプリント表現や入力構文をもたず、何であれ、それらの基本型としてプリントされます。

パース関数およびプリント関数を含む、ストリームに関連した関数の説明は、Reading and Printing Lisp Objectsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.10 Keymap Type

キーマップ(keymap)は、ユーザーがタイプした文字を、コマンドにマップします。このマップは、ユーザーのコマンド入力が実行される方法を制御します。キーマップは、実際にはCARがシンボルkeymapのリストです。

キーマップの作成、プレフィクスキーの処理、ローカルキーマップやグローバルキーマップ、キーバインドの変更についての情報は、Keymapsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.11 Overlay Type

オーバーレイ(overlay)は、バッファーの一部に適用するプロパティーを指定します。それぞれのオーバーレイはバッファーの指定された範囲に適用され、プロパティーリスト(プロパティー名と値が交互に記述された要素のリスト)を含みます。オーバーレイプロパティーは、バッファーの指定された一部を、一時的に異なるスタイルで表示するために使用されます。オーバーレイは入力構文をもたず、バッファーメイト範囲の位置を与えるハッシュ表記でプリントされます。

オーバーレイを作成したり使用する方法についての情報は、Overlaysを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4.12 Font Type

fontは、グラフィカルな端末上のテキストを表示する方法を指定します。実際には異なる3つのフォント型 — フォントオブジェクト(font objects)フォントスペック(font specs)フォントエンティティー(font entities) — が存在しますこれらは入力構文をもちません。これらのプリント構文は、‘#<font-object>’、‘#<font-spec>’、‘#<font-entity>’のようになります。これらのLispオブジェクトの説明は、Low-Level Font Representationを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 Read Syntax for Circular Objects

複雑なLispオブジェクトにおける共有された構造、または循環する構造を表すために、リーダー構成‘#n=’と‘#n#’を使用することができます。

後でオブジェクトを参照するには、オブジェクトの前で#n=を使用します。その後で、他の場所にある同じオブジェクトを参照するために、#n#を使用することができます。ここでnは任意の整数です。たとえば以下は、1番目の要素が3番目の要素にも繰り替えされるリストを作成する方法です:

(#1=(a) b #1#)

これは、以下のような通常の構文とは異なります

((a) b (a))

これは1番目の要素と3番目の要素がそっくりなリストですが、これらは同じLispオブジェクトではありません。以下で違いを見ることができます:

(prog1 nil
  (setq x '(#1=(a) b #1#)))
(eq (nth 0 x) (nth 2 x))
     ⇒ t
(setq x '((a) b (a)))
(eq (nth 0 x) (nth 2 x))
     ⇒ nil

“要素”として自身を含むような、循環する構造を作成するために、同じ構文を使用できます。以下は例です:

#1=(a #1#)

これは、2番目の要素がそのリスト自身であるリストを作成します。これが実際にうまくいくのか、以下で確認できます:

(prog1 nil
  (setq x '#1=(a #1#)))
(eq x (cadr x))
     ⇒ t

変数print-circleを非nil値にバインドした場合、Lispプリンターは、循環および共有されるLispオブジェクトを記録するこの構文を、生成することができます。Variables Affecting Outputを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.6 Type Predicates

Emacs Lispインタープリター自身は、関数が呼び出されたときに、その関数に渡された実際の引数にたいする型チェックは行ないません。それが行なえないのは、Lispにおける関数の引数は、他のプログラミング言語のようなデータ型宣言をもたないからです。したがって実際の引数が、その関数が使用できる型に属するかどうかをテストするのは、それぞれの関数に任されています。

すべてのビルトイン関数は、適切なときに実際の引数の型チェックを行い、引数の型が違う場合は、wrong-type-argumentエラーをシグナルします。たとえば以下は、+の引数に、+が扱うことができない引数を渡したとき何が起こるかの例です:

(+ 2 'a)
     error→ Wrong type argument: number-or-marker-p, a

異なる型にたいして異なる処理をプログラムに行なわせる場合は、明示的に型チェックを行なわなければなりません。オブジェクトの型をチェックするもっとも一般的な方法は、型述語(type predicate)関数の呼び出しです。Emacsはそれぞれの型にたいする型述語をもち、組み合わされた型にたいする述語もあります。

型述語関数は1つの引数をとり、その引数が適切な型であればt、そうでない場合はnilをreturnします。述語関数にたいする一般的なLisp慣習にしたがい、ほとんどの型述語の名前は、‘p’で終わります。

以下はリストにたいしてチェックを行なう述語listpと、シンボルにたいしてチェックを行なう述語symbolpの例です。

(defun add-on (x)
  (cond ((symbolp x)
         ;; If X is a symbol, put it on LIST.
         (setq list (cons x list)))
        ((listp x)
         ;; If X is a list, add its elements to LIST.
         (setq list (append x list)))
        (t
         ;; We handle only symbols and lists.
         (error "Invalid argument %s in add-on" x))))

以下の表は、事前定義された型述語(アルファベット順)と、さらに情報を得るためのリファレンスです。

atom

atomを参照してください。

arrayp

arraypを参照してください。

bool-vector-p

bool-vector-pを参照してください。

bufferp

bufferpを参照してください。

byte-code-function-p

byte-code-function-pを参照してください。

case-table-p

case-table-pを参照してください。

char-or-string-p

char-or-string-pを参照してください。

char-table-p

char-table-pを参照してください。

commandp

commandpを参照してください。

consp

conspを参照してください。

custom-variable-p

custom-variable-pを参照してください。

display-table-p

display-table-pを参照してください。

floatp

floatpを参照してください。

fontp

Low-Level Font Representationを参照してください。

frame-configuration-p

frame-configuration-pを参照してください。

frame-live-p

frame-live-pを参照してください。

framep

framepを参照してください。

functionp

functionpを参照してください。

hash-table-p

hash-table-pを参照してください。

integer-or-marker-p

integer-or-marker-pを参照してください。

integerp

integerpを参照してください。

keymapp

keymappを参照してください。

keywordp

Variables that Never Changeを参照してください。

listp

listpを参照してください。

markerp

markerpを参照してください。

wholenump

wholenumpを参照してください。

nlistp

nlistpを参照してください。

numberp

numberpを参照してください。

number-or-marker-p

number-or-marker-pを参照してください。

overlayp

overlaypを参照してください。

processp

processpを参照してください。

sequencep

sequencepを参照してください。

stringp

stringpを参照してください。

subrp

subrpを参照してください。

symbolp

symbolpを参照してください。

syntax-table-p

syntax-table-pを参照してください。

vectorp

vectorpを参照してください。

window-configuration-p

window-configuration-pを参照してください。

window-live-p

window-live-pを参照してください。

windowp

windowpを参照してください。

booleanp

booleanpを参照してください。

string-or-null-p

string-or-null-pを参照してください。

あるオブジェクトがどの型かチェックするもっとも一般的な方法は、関数type-ofの呼び出しです。オブジェクトは、ただ1つだけの基本型に属することを思い出してください。type-ofは、それがどの型(Lisp Data Typesを参照してください)か告げます。しかしtype-ofは基本型以外の型については何も知りません。ほとんどの場合、type-ofより型述語を使用するほうが便利でしょう。

Function: type-of object

この関数はobjectの基本型を名前とする、シンボルをreturnします。retuen値はシンボルbool-vectorbufferchar-tablecompiled-functionconsfloatfont-entityfont-objectfont-specframehash-tableintegermarkeroverlayprocessstringsubrsymbolvectorwindowwindow-configurationのうちの1つです。

(type-of 1)
     ⇒ integer
(type-of 'nil)
     ⇒ symbol
(type-of '())    ; ()nilです。
     ⇒ symbol
(type-of '(x))
     ⇒ cons

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.7 Equality Predicates

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

Function: eq object1 object2

この関数はobject1object2が同じオブジェクトの場合はt、それ以外はnilをreturnします。

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

(eq 'foo 'foo)
     ⇒ t

(eq 456 456)
     ⇒ t

(eq "asdf" "asdf")
     ⇒ nil

(eq "" "")
     ⇒ t
;; この例外は省スペースのためにEmacs Lispが
;; ただ1つのマルチバイトの空文字列を作成するためです。

(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されていないシンボルをreturnします。これはLisp式内で、その名前を記述したシンボルとは区別されます。同じ名前の、異なるシンボルは、eqではありません。Creating and Interning Symbolsを参照してください。

(eq (make-symbol "foo") 'foo)
     ⇒ nil
Function: equal object1 object2

この関数は、object1object2が同じ構成要素をもつ場合はt、それ以外はnilをreturnします。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

文字列の比較は大文字小文字を区別しますが、テキストプロパティーは考慮しません — これは文字列内の文字だけを比較します。Text Propertiesを参照してください。テキストプロパティーも比較する場合は、equal-including-propertiesを使用します。記述的な理由により、ユニバイト文字列とマルチバイト文字列は、それらが同じ文字シーケンスを含み、それらすべてのコードが0から127(ASCII)、または160から255(8ビットグラフィック)の場合に限り、equalです(Text Representationsを参照してください)。

(equal "asdf" "ASDF")
     ⇒ nil

しかし2つの別のバッファーは、それらのテキスト内容が同じでも、equalと判断されることはありません。

equalのテストは再帰により実装されています。たとえば2つのコンスセルxyを与えると、(equal x y)は、以下の式の両方がtをreturnする場合に限り、tをreturnします:

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

これは再帰処理なので、循環するリストがあると無限再帰となります(エラーとなります)。

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

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3 Numbers

GNU Emacsは2つの数値データ型 — 整数(integers)浮動小数点数(floating-point numbers)をサポートします。整数は-3、0、7、13、511などの整数です。浮動小数点数は-4.5、0.0、2.71828などの小数部をもちます・これらは指数記数法でも表現できます — ‘1.5e2’は‘150.0’と同じです。ここで‘e2’は10の2乗をあらわし、それに1.5を乗じるという意味です。整数計算は正確であり、オーバーフローするときもあります。浮動小数点数の計算においては、数値は固定された精度をもつため、、しばしば丸め誤差(rounding errors)を引き起こします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Integer Basics

整数の値の範囲はマシンに依存します。最小の範囲は-536,870,912から536,870,911(30ビット長の -2**29 から 2**29 - 1) ですが、多くのマシンはこれより広い範囲を提供します。このチャプターの例の多くは、最小の整数は30ビット長であると仮定します。

Lispリーダーは、(オプションで最初の符号記号と、最後のピリオドをともなう)数字のシーケンスとして整数を読み取ります。Emacsの範囲を超える整数は、浮動小数点数として扱われます。

 1               ; 整数1。
 1.              ; 整数1。
+1               ; これも整数1。
-1               ; 整数-1。
 9000000000000000000
                 ; 浮動小数点数9e18.
 0               ; 整数0
-0               ; 整数0

基数が10以外の整数の構文は、‘#’の後に基数を指定する文字 — 2進は‘b’、8進は‘o’、16進は‘x’、‘radixr’は基数radix — を記述します。基数を指定する文字の大文字小文字は区別されません。したがって‘#binteger’はintegerを2進として読み取り、‘#radixrinteger’はintegerを基数radixとして読み取ります。radixに指定できる値は2から36です。たとえば:

#b101100 ⇒ 44
#o54 ⇒ 44
#x2c ⇒ 44
#24r1k ⇒ 44

整数にたいして処理を行なうさまざまな関数、特にビット演算(Bitwise Operations on Integersを参照してください)を理解するためには、数を2進形式で見ることが助けになることがしばしばあります。

30ビットの2進では、10進数の整数5は以下のようになります:

0000...000101 (全部で30ビット)

(‘...’は30ビットのワードを満たすのに充分なビットを意味し、この場合の‘...’は12個の0ビットを意味します。以下の例でも、2進の整数を読みやすくするために、‘...’の表記を使用します)

整数の-1は、以下のようになります:

1111...111111 (全部で30ビット)

-1は30個の1で表現されます(これは2の補数表記と呼ばれます)。

-1から4を減じることにより、負の整数-5が得られます。10進の整数4は、2進では100です。したがって、-5は以下のようになります:

1111...111011 (全部で30ビット)

この実装では、0ビットの2進の最大は、10進の536,870,911です。これは2進では以下のようになります:

0111...111111 (全部で30ビット)

算術関数は整数が範囲の外かをチェックしないので、536,870,911に1を加えると、その値は負の整数-536,870,912になります:

(+ 1 536870911)
     ⇒ -536870912
     ⇒ 1000...000000 (全部で30ビット)

このチャプターで説明する多くの関数は、数字の位置として引数にマーカー(Markersを参照してください)を受け取ります。そのような関数にたいする実際の引数は数字かマーカーなので、わたしたちはこれらの引数にnumber-or-markerという名前を与えることがあります。引数の値がマーカーの場合、マーカーの位置が使用され、マーカーのバッファーは無視されます。

Variable: most-positive-fixnum

この変数の値は、Emacs Lispが扱える整数の最大値です。典型的な値は32ビットでは 2**29 - 1 、64ビットでは 2**61 - 1 です。

Variable: most-negative-fixnum

この変数の値は、Emacs Lispが扱える最小の整数です。これは負の整数です。典型的な値は32ビットでは -2**29 、64ビットでは -2**61、 です。

Emacs Lispでは、テキスト文字は整数により表現されます。0から(max-char)までの整数は、有効な文字として判断されます。Character Codesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 Floating-Point Basics

浮動小数点数は整数ではない数を表現するのに便利です。浮動小数点数の範囲は、使用しているマシンでのCデータ型のdoubleと同じ範囲です。現在Emacsでサポートされているすべてのコンピューターでは、これは倍精度のIEEE浮動小数点数です。

浮動小数点数にたいする入力構文は、小数点と指数のどちらか1つ、または両方が必要とします。オプションの符号(‘+’か‘-’)は、その数字と指数の前に記述します。たとえば、‘1500.0’、‘+15e2’、‘15.0e+2’、‘+1500000e-3’、‘.15e4’は、値が1500の浮動小数点数を記述する5つの方法です。これらはすべて等価です。Common Lispと同様、Emacs Lispは、浮動小数点数の小数点の後に、少なくとも1つの数字を必要とします。‘1500.’は整数であり、浮動小数点数ではありません。

Emacs Lispは-0.0を、equal=に関して、通常の0と数学的に同じものとして扱います。これは、(他の処理がこれらを区別するとしても、-0.00.0は数学的に等しいとする)IEEE浮動小数点数規格にしたがっています。

IEEE浮動小数点数規格は、浮動小数点数として、正の無限大と、負の無限大をサポートします。この規格はNaNまたは“not-a-number(数字ではない)”と呼ばれる値クラスも提供します。数学関数は、正しい答えが存在しないような場合に、このような値をreturnします。たとえば(/ 0.0 0.0)はNaNをreturnします。NaN値に符号がついていたとしても、実用的な目的にたいして、Emacs Lispにおける異なるNaN値に、意味のある違いはありません。

以下は、これらの特別な浮動小数点数にたいする入力構文です:

infinity

1.0e+INF’と‘-1.0e+INF

not-a-number

0.0e+NaN’と‘-0.0e+NaN

以下の関数は浮動小数点数を扱うために特化したものです:

Function: isnan x

この述語は浮動小数引数がNaNのときはt、それ以外はnilをreturnします。

Function: frexp x

この関数はコンスセル(s . e)をreturnします。ここでseは、浮動小数点数のsignificand(浮動小数点数を2の指数表現したときの仮引数)と指数です。

xが有限の場合、sは0.5以上1.0未満の浮動小数点数で、eは整数で、 x = s * 2**eです。 xが0または無限の場合、sxと等しくなります。xがNaNの場合は、sもNaNです。xが0の場合、eは0です。

Function: ldexp sig &optional exp

この関数は、significandがsig、指数がexpの浮動小数点数をreturnします。

Function: copysign x1 x2

koの関数はx2の、x1の値にコピーして、その結果をreturnします。x1x2は浮動小数でなければなりません。

Function: logb x

この関数はxの2進指数をreturnします。より正確にいうと、この値は|x|の2を底とする対数を、整数に切り下げたものです。

(logb 10)
     ⇒ 3
(logb 10.0e20)
     ⇒ 69

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Type Predicates for Numbers

このセクションの関数は、数または数の特定の型にたいしてテストを行ないます。関数integerpおよびfloatpは、引き数として任意のLispオブジェクト型をとることができます(そうでないと、あまり使用する機会がありません)。しかし、述語zeropは、引き数として数を要求します。Predicates on Markersinteger-or-marker-pnumber-or-marker-pも参照してください。

Function: floatp object

この述語は、引数が浮動小数かどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: integerp object

この述語は引数が整数かどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: numberp object

この述語は引数が数(整数か浮動小数)かどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: natnump object

この述語(名前は“natural number(自然数)”が由来です)は、引数が正の整数かどうかをテストして、もしそうならt、それ以外はnilをreturnします。0は整数と判断されます。

wholenumpは、natnumpにたいするシノニムです。

Function: zerop number

この述語は、引数が0かどうかをテストして、もしそうならt、それ以外はnilをreturnします。引数は数でなければなりません。

(zerop x)は、(= x 0)と等価です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Comparison of Numbers

数が数値的に等しいかテストするためには、eqではなく、通常は=を使用するべきです。同じ数値をもつ、多くの浮動小数オブジェクトが存在するかもしれません。これらを比較するのにeqを使用する場合、これは2つの値が同じオブジェクトかどうかをテストすることになります。対照的に、=はオブジェクトの数値的な値だけを比較します。

Emacs Lispでは、それぞれの整数はは、一意なLispオブジェクトです。したがって、整数に関しては、eq=と同じです。未知の整数の値を比較するのに、eqを使用するのが便利な場合があります。なぜなら未知の値が数字でない場合でも、eqはエラーを報告しません。対照的に、引数が数でもマーカーでもない場合、=はエラーをシグナルします。しかし、整数の比較においてさえ、使用できる場合は=を使用するのが、よいプログラミング習慣です。

数の比較において、2つの数が同じデータ型(どちらも整数、またはどちらも浮動小数)で、同じ値の場合は等しい数として扱う、equalのほうが便利なときもあります。対照的に、=は、整数と浮動小数点数を等しい数と扱うことができます。Equality Predicatesを参照してください。

他の欠点もあります。浮動小数演算は正確ではないので、浮動小数値を比較するのが悪いアイデアのときが、しばしばあります。通常は、近似的に等しいことをテストするほうがよいでしょう。以下はこれを行なう関数です:

(defvar fuzz-factor 1.0e-6)
(defun approx-equal (x y)
  (or (= x y)
      (< (/ (abs (- x y))
            (max (abs x) (abs y)))
         fuzz-factor)))

Common Lispに関する注意: Common Lispは複数ワード整数を実装していて、2つの別の整数オブジェクトが、同じ数値的な値をもつことができるので、Common Lispでの数の比較は、常に=が要求されます。Emacs Lispの整数は範囲が制限されているため、与えられた値に対応する整数オブジェクトは、1つだけです。

Function: = number-or-marker &rest number-or-markers

この関数は、すべての引数が数値的に等しいかどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: eql value1 value2

この関数はeqと同様に振る舞いますが、引数が両方とも数のときは例外です。これは数を型と数値的な値により比較するので、(eql 1.0 1)nilをreturnしますが、(eql 1.0 1.0)(eql 1 1)tをreturnします。

Function: /= number-or-marker1 number-or-marker2

この関数は引数が数値的に等しいかどうかをテストして、もし異なる場合はt、等しい場合はnilをreturnします。

Function: < number-or-marker &rest number-or-markers

この関数は、各引数がそれぞれ、その後の引数より小さいかどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: <= number-or-marker &rest number-or-markers

この関数は、各引数がそれぞれ、その後の引数以下かどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: > number-or-marker &rest number-or-markers

この関数は、各引数がそれぞれ、その後の引数より大きいかどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: >= number-or-marker &rest number-or-markers

この関数は、各引数がそれぞれ、その後の引数以上かどうかをテストして、もしそうならt、それ以外はnilをreturnします。

Function: max number-or-marker &rest numbers-or-markers

この関数は引数の最大をreturnします。引数のどれかが浮動小数の場合は、たとえ最大が整数であっても、浮動小数として値がreturnされます。

(max 20)
     ⇒ 20
(max 1 2.5)
     ⇒ 2.5
(max 1 3 2.5)
     ⇒ 3.0
Function: min number-or-marker &rest numbers-or-markers

この関数は引数の最小をreturnします。引数のどれかが浮動小数の場合は、たとえ最小が整数であっても、浮動小数として値がreturnされます。

(min -4 1)
     ⇒ -4
Function: abs number

この関数はnumberの絶対値をreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 Numeric Conversions

整数を浮動少数に変換するには、関数floatを使用します。

Function: float number

これは浮動小数に変換されたnumberをreturnします。すでにnumberが浮動小数の場合、floatはそれを変更せずにreturnします。

浮動小数点数を整数に変換する関数が4つあります。これらは浮動小数点数を丸める方法がことなります。これらはすべて引数numberと、オプション引数としてdivisorを受け取ります。引数は両方とも整数または浮動小数点数です。divisornilのこともあります。divisornilまたは省略された場合、これらの関数はnumberを整数に変換するか、それが既に整数の場合は変更せずにreturnします。divisorが非nilの場合、これらの関数はnumberdivisorで除してから、その結果を整数に変換します。divisorが(整数か浮動小数かに関わらず)0の場合、Emacsはarith-errorエラーをシグナルします。

Function: truncate number &optional divisor

これは0に向かって丸めることにより整数に変換したnumberをreturnします。

(truncate 1.2)
     ⇒ 1
(truncate 1.7)
     ⇒ 1
(truncate -1.2)
     ⇒ -1
(truncate -1.7)
     ⇒ -1
Function: floor number &optional divisor

これは、下方(負の無限大に向かって)に丸めることにより整数に変換したnumberをreturnします。

divisorが指定された場合、modに相当する種類の除算演算を使用して、下方に丸めを行ないます。

(floor 1.2)
     ⇒ 1
(floor 1.7)
     ⇒ 1
(floor -1.2)
     ⇒ -2
(floor -1.7)
     ⇒ -2
(floor 5.99 3)
     ⇒ 1
Function: ceiling number &optional divisor

これは、上方(正の無限大に向かって)に丸めることにより整数に変換したnumberをreturnします。

(ceiling 1.2)
     ⇒ 2
(ceiling 1.7)
     ⇒ 2
(ceiling -1.2)
     ⇒ -1
(ceiling -1.7)
     ⇒ -1
Function: round number &optional divisor

これは、もっとも近い整数に向かって丸めることにより整数に変換したnumberをreturnします。2つの整数から等距離にある値の丸めでは、偶数の整数をreturnします。

(round 1.2)
     ⇒ 1
(round 1.7)
     ⇒ 2
(round -1.2)
     ⇒ -1
(round -1.7)
     ⇒ -2

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6 Arithmetic Operations

Emacs Lispは伝統的な4つの算術演算(加減乗除)、同様に剰余とmodulusの関数、および1加算、1減算の関数を提供します。%を除き、これらの各関数は引き数として整数か浮動小数を受け取り、浮動小数の引数がある場合は、浮動小数点数をreturnします。

Emacs Lispの算術関数は整数のオーバーフローをチェックしません。したがって(1+ 536870911)は-536870912に評価されるかもしれず、それはハードウェアーに依存します。

Function: 1+ number-or-marker

この関数はnumber-or-marker + 1をreturnします。例えば、

(setq foo 4)
     ⇒ 4
(1+ foo)
     ⇒ 5

この関数はCの演算子++とは類似しません — この関数は変数をインクリメントしません。この関数は和を計算するだけです、したがって以下を続けて評価すると、

foo
     ⇒ 4

変数をインクリメントしたい場合は、以下のようにsetqを使用しなければなりません:

(setq foo (1+ foo))
     ⇒ 5
Function: 1- number-or-marker

この関数はnumber-or-marker - 1をreturnします。

Function: + &rest numbers-or-markers

この関数は引数すべてを加算します。引数を与えない場合、+は0をreturnします。

(+)
     ⇒ 0
(+ 1)
     ⇒ 1
(+ 1 2 3 4)
     ⇒ 10
Function: - &optional number-or-marker &rest more-numbers-or-markers

-関数は2つの目的 — 符号反転と減算 —を果たします。-に1つの引数を与えた場合、値は引数の符号を反転したものになります。複数の引数がある場合、number-or-markerからmore-numbers-or-markersまでの各値を蓄積的に減算します。引数がない場合、結果は0です。

(- 10 1 2 3 4)
     ⇒ 0
(- 10)
     ⇒ -10
(-)
     ⇒ 0
Function: * &rest numbers-or-markers

この関数はすべての引数を乗じて、積をreturnします。引数がない場合、*は1をreturnします。

(*)
     ⇒ 1
(* 1)
     ⇒ 1
(* 1 2 3 4)
     ⇒ 24
Function: / dividend divisor &rest divisors

この関数はdividenddivisorで除し、商をreturnします。追加の引数divisorsがある場合、その後さらにdividenddivisorsで順に除します。各引数は数かマーカーです。

すべての引数が整数の場合、結果は各除算の後に商を0へ向かって丸めることにより得られる整数になります。

(/ 6 2)
     ⇒ 3
(/ 5 2)
     ⇒ 2
(/ 5.0 2)
     ⇒ 2.5
(/ 5 2.0)
     ⇒ 2.5
(/ 5.0 2.0)
     ⇒ 2.5
(/ 25 3 2)
     ⇒ 4
(/ -17 6)
     ⇒ -2

整数を整数0で除すると、Emacsはarith-errorエラー(Errorsを参照してください)をシグナルします。浮動小数の除算においては、0でない数を0で除することにより、正の無限大または負の無限大を得ます(Floating-Point Basicsを参照してください)。

Function: % dividend divisor

この関数は、dividenddivisorで除した後、その剰余を整数でreturnします。引数は整数かマーカーでなければなりません。

任意の2つの整数dividenddivisorにたいして、

(+ (% dividend divisor)
   (* (/ dividend divisor) divisor))

は、divisorが非0の場合は常にdividendと等しくなります。

(% 9 4)
     ⇒ 1
(% -9 4)
     ⇒ -1
(% 9 -4)
     ⇒ 1
(% -9 -4)
     ⇒ -1
Function: mod dividend divisor

この関数はdividenddivisorにたいするmodulo、言い換えるとdividenddivisorで除した後の剰余(ただし符号はdivisorと同じ)えおreturnします。引数は数かマーカーでなければなりません。

%とは異なり、modは浮動小数の引数を許容します。これは商を整数に下方(負の無限大に向かって)へ丸めて、剰余を計算するのにこの商を使用します。

divisorが0のときmodは、両方の引数が整数の場合はarith-errorエラーをシグナルし、それ以外はNaNをreturnします。

(mod 9 4)
     ⇒ 1
(mod -9 4)
     ⇒ 3
(mod 9 -4)
     ⇒ -3
(mod -9 -4)
     ⇒ -1
(mod 5.5 2.5)
     ⇒ .5

任意の2つの数dividenddivisorにたいして、

(+ (mod dividend divisor)
   (* (floor dividend divisor) divisor))

は常にdividendになります(ただし引数のどちらかが浮動小数の場合は丸め誤差の範囲内で等しく、dividendが整数でdivisorが0の場合はarith-errorとなります)。floorについては、Numeric Conversionsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.7 Rounding Operations

関数ffloorfceilingfroundftruncateは、浮動小数の引数をとり、値が近くの整数であるような浮動少数をreturnします。ffloorは一番近い下方の整数、fceilingは一番近い上方の整数、ftruncateは0に向かう方向で一番近い整数、froundは一番近い整数をreturnします。

Function: ffloor float

この関数はfloatを次に小さい整数値に丸めて、その値を浮動小数点数としてreturnします。

Function: fceiling float

この関数はfloatを次に大きい整数値に丸めて、その値を浮動小数点数としてreturnします。

Function: ftruncate float

この関数はfloatを0方向の整数値に丸めて、その値を浮動小数点数としてreturnします。

Function: fround float

この関数はfloatを一番近い整数値に丸めて、その値を浮動小数点数としてreturnします。2つの整数値との距離が等しい値にたいする丸めでは、偶数の整数をreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.8 Bitwise Operations on Integers

コンピューターの中では、整数はビット(bit: 0か1の数字)のシーケンスである、2進数で表されます。ビット演算は、そのようなシーケンスの中の個々のビットに作用します。たとえば、シフト(shifting)はシーケンス全体を1つ以上左または右に移動して、“移動された”のと同じパターンを再生します。

Emacs Lispのビット演算は、整数だけに適用されます。

Function: lsh integer1 count

lshlogical shiftの略で、integer1のビットを左にcount個シフトします。countが負の場合は右にシフトし、シフトにより空きになったビットには0がセットされます。count isが負の場合、lshは左端(最上位)に0をシフトするので、integer1が負の場合でも、正の結果が生成されます。これと対照的なのが、以下で説明するashです。

以下に、lshでビットパターンの位置を1つ左にシフトする例を2つ紹介します。ここでは下位8ビットの2進パターンだけを表示しており、残りのビットはすべて0です。

(lsh 5 1)
     ⇒ 10
;; 10進の5は、10進の10になります。
00000101 ⇒ 00001010

(lsh 7 1)
     ⇒ 14
;; 10進の7は、10進の14になります。
00000111 ⇒ 00001110

この例が説明するように、ビットパターンを左に1シフトすると、生成される数は、元の数の2倍になります。

ビットパターンを左に2シフトすると、以下(8ビット2進数)の結果が生成されます:

(lsh 3 2)
     ⇒ 12
;; 10進の3は、10進の12になります。
00000011 ⇒ 00001100

一方、右に1シフトすると、以下のようになります:

(lsh 6 -1)
     ⇒ 3
;; 10進の6は10進の3になります。
00000110 ⇒ 00000011

(lsh 5 -1)
     ⇒ 2
;; 10進の5は、10進の2になります。
00000101 ⇒ 00000010

例が明かにするように、右に1シフトすることにより、正の整数の値が2で除され、下方に丸められます。

関数lshは、他のEmacs Lisp算術関数と同様、オーバーフローをチェックしないので、左にシフトすることにより上位ビットが捨てられ、その数の符号が変化するかもしれません。たとえば30ビットの実装では、536,870,911を左にシフトすると、-2が生成されます。

(lsh 536870911 1)          ; 左シフト
     ⇒ -2

2進では、この引数は以下のようになります:

;; 10進の536,870,911
0111...111111 (全部で30ビット)

これを左にシフトすると、以下のようになります:

;; 10進の-2
1111...111110 (全部で30ビット)
Function: ash integer1 count

ash (算術シフト(arithmetic shift))は、integer1の中のビット位置を左にcountシフトします。countが負の場合は右にシフトします。

ashlshと同じ結果を与えますが、例外はinteger1countがとみに負の場合です。この場合、lshは左にできる空きビットに0を置きますが、ashは1を置きます。

したがってashでビットパターンの位置を右に1シフトすると、以下のようになります:

(ash -6 -1) ⇒ -3
;; 10進の-6は、10進の-3になります
1111...111010 (30 bits total)
     ⇒
1111...111101 (30 bits total)

対照的に、lshでビットパターンの位置を1右にシフトすると、以下のようになります:

(lsh -6 -1) ⇒ 536870909
;; 10進の-6は、10進の536,870,909になります。
1111...111010 (30 bits total)
     ⇒
0111...111101 (30 bits total)

他にも例を示します:

                   ;         30ビットの2進数

(lsh 5 2)          ;   5  =  0000...000101
     ⇒ 20         ;      =  0000...010100
(ash 5 2)
     ⇒ 20
(lsh -5 2)         ;  -5  =  1111...111011
     ⇒ -20        ;      =  1111...101100
(ash -5 2)
     ⇒ -20
(lsh 5 -2)         ;   5  =  0000...000101
     ⇒ 1          ;      =  0000...000001
(ash 5 -2)
     ⇒ 1
(lsh -5 -2)        ;  -5  =  1111...111011
     ⇒ 268435454
                   ;      =  0011...111110
(ash -5 -2)        ;  -5  =  1111...111011
     ⇒ -2         ;      =  1111...111110
Function: logand &rest ints-or-markers

この関数は、引数の“論理積(logical and)”をreturnします。すべての引数のn番目のビットがセットされている場合に限り、結果のn番目のビットがセットされます(“セット”とは、そのビットの値が0ではなく1であることを意味します)。

たとえば、13と12の“論理積”は — 4ビット2進数を使用すると1101と1100の論理積は1100を生成します。この2進数では両方とも、左の2ビットがセット(つまり1)されているので、returnされる値の左2ビットがセットされます。しかし右の2ビットにたいしては、少なくとも1つの引数でそのビットが0なので、returnされる値の右2ビットは0になります。

したがって、

(logand 13 12)
     ⇒ 12

logandに何の引数も綿さない場合は、値-1がreturnされます。-1を2進数で表すとすべてのビットが1なので、-1はlogandにたいする単位元(identity element)です。

                   ;        30ビット2進数

(logand 14 13)     ; 14  =  0000...001110
                   ; 13  =  0000...001101
     ⇒ 12         ; 12  =  0000...001100

(logand 14 13 4)   ; 14  =  0000...001110
                   ; 13  =  0000...001101
                   ;  4  =  0000...000100
     ⇒ 4          ;  4  =  0000...000100

(logand)
     ⇒ -1         ; -1  =  1111...111111
Function: logior &rest ints-or-markers

この関数は、引数の“論理和(inclusive or)”をreturnします。少なくとも1つの引数でn番目のビットがセットされていれば、結果のn番目のビットがセットされます。引数を与えない場合の結果は、この処理にたいする単位元である0です。logiorに渡す引数が1つだけの場合、その引数がreturnされます。

                   ;        30ビット2進数

(logior 12 5)      ; 12  =  0000...001100
                   ;  5  =  0000...000101
     ⇒ 13         ; 13  =  0000...001101

(logior 12 5 7)    ; 12  =  0000...001100
                   ;  5  =  0000...000101
                   ;  7  =  0000...000111
     ⇒ 15         ; 15  =  0000...001111
Function: logxor &rest ints-or-markers

この関数は、引数の“排他的論理和(exclusive or)”をreturnします。n番目のビットがセットされている引数の数が奇数個の場合だけ、結果のn番目のビットがセットされます。引数を与えない場合の結果は、この処理の単位元である0となります。logxorに渡す引数が1つだけの場合、その引数がreturnされます。

                   ;        30ビット2進数

(logxor 12 5)      ; 12  =  0000...001100
                   ;  5  =  0000...000101
     ⇒ 9          ;  9  =  0000...001001

(logxor 12 5 7)    ; 12  =  0000...001100
                   ;  5  =  0000...000101
                   ;  7  =  0000...000111
     ⇒ 14         ; 14  =  0000...001110
Function: lognot integer

この関数は引数の論理的な補数(logical complement)をreturnします。integern番目のビットが0の場合に限り、結果のn番目のビットが1になります。逆も成り立ちます。

(lognot 5)
     ⇒ -6
;;  5  =  0000...000101 (全部で30ビット)
;; becomes
;; -6  =  1111...111010 (全部で30ビット)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9 Standard Mathematical Functions

これらの数学的関数は、引き数として整数と同様に浮動小数点数も許容します。

Function: sin arg
Function: cos arg
Function: tan arg

これらは三角関数です、引数argはラジアン単位です。

Function: asin arg

(asin arg)の値は、sinの値がargとなるような -pi/2 から pi/2 (境界値を含む)の数です。argが範囲外([-1, 1]の外)の場合、asinはNaNをreturnします。

Function: acos arg

(acos arg)の値は、cosの値がargとなるような、0から pi (境界値を含む)の数です。argが範囲外([-1, 1]の外)の場合、acosはNaNをreturnします。

Function: atan y &optional x

(atan y)の値は、tanの値がyとなるような、 -pi/2 から pi/2 (境界値を含まない)の数です。オプションの第2引数xが与えられた場合、(atan y x)の値はベクトル[x, y]X軸が成す角度のラジアン値です。

Function: exp arg

これは指数関数です。この関数はeの指数argをreturnします。

Function: log arg &optional base

この関数は底をbaseとするargの対数をreturnします。baseを指定しない場合、自然底(natural base)eが使用されます。argまたhbaseが負の場合、logはNaNをreturnします。

Function: expt x y

この関数はxyを乗じてreturnします。引数が両方とも整数で、yが正の場合、結果は整数になります。この場合オーバーフローによる切り捨てが発生するので、注意してください。xが有限の負数で、yが有限の非整数の場合、exptはNaNをreturnします。

Function: sqrt arg

これはargの平方根をreturnします。argが有限で0より小さい場合、sqrtはNaNをreturnします。

加えて、Emacsは以下の数学的な定数を定義します:

Variable: float-e

自然対数e(2.71828…)。

Variable: float-pi

円周率pi(3.14159…)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.10 Random Numbers

決定論的なコンピュータープログラムでは、真の乱数を生成することはできません。しかしほとんどの目的には、疑似乱数(pseudo-random numbers)で充分です。一連の疑似乱数は、決定論的な手法により生成されます。真の乱数ではありませんが、それらにはランダム列を模する特別な性質があります。たとえば疑似ランダム系では、すべての可能な値は、均等に発生します。

疑似乱数は“シード(seed: 種)”から生成されます。与えられた任意のシードから開始することにより、random関数は常に同じ数列を生成します。デフォルトでは、Emacsは開始時に乱数シードを初期化することにより、それぞれのEmacsの実行において、randomの値シーケンスは(ほとんど確実に)異なります。

再現可能な乱数シーケンスが欲しい場合もあります。たとえば乱数シーケンスに依存するプログラムをデバッグする場合、プログラムの各実行において同じ挙動を得ることが助けになります。再現可能なシーケンスを作成するには、(random "")を実行します。これは特定のEmacsの実行可能ファイルにたいして、シードに定数値をセットします(しかし、この実行可能ファイルは、その他のEmacsビルドと異なるものになるでしょう)。シード値として、他のさまざまな文字列を使用することができます。

Function: random &optional limit

この関数は疑似乱数の整数をreturnします。繰り返し呼び出すと、一連の疑似乱数の整数をreturnします。

limitが正の整数の場合、値は負ではないlimit未満の値から選択されます。それ以外では、値はmost-negative-fixnumからmost-positive-fixnumの間の、Lispで表現可能な任意の整数(Integer Basicsを参照してください)になるでしょう。

limittの場合は、Emacsを再起動したときに、新しいシードを選択することを意味します。

limitが文字列の場合、その文字列定数にもとづいた新しいシードを選択することを意味します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4 Strings and Characters

Emacs Lispの文字列は、文字列の順序列(ordered sequence)を含む配列です。文字列はシンボル、バッファー、ファイルの名前に使用されます。その他にも、ユーザーにたいしてメッセージを送ったりバッファー間でコピーする文字列を保持したり等の、他の多くの目的にたいして使用されます。文字列は特に重要なので、Emacs Lispは特別に文字列を操作するための、多くの関数をもちます。Emacs Lispプログラムは、個々の文字より、文字列を多用します。

キーボードの文字イベントの文字列にたいする特別な考慮は、Putting Keyboard Events in Stringsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 String and Character Basics

文字(character)とは、テキスト内の1つの文字を表すLispオブジェクトです。Emacs Lispでは、文字は単なる整数です。ある整数が文字か文字でないかを区別するのは、それが使用される方法だけです。Emacsでの文字表現についての詳細は、Character Codesを参照してください。

文字列(string)とは、固定された文字シーケンスです。これは配列(array)と呼ばれるシーケンス型で、配列長が固定で、1度作成したら変更できないことを意味します(Sequences, Arrays, and Vectorsを参照してください)。Cとは異なり、Emacs Lispの文字列は文字コードを判断することにより終端されません

文字列は配列であり、したがって同様にシーケンスでもあるので、Sequences, Arrays, and Vectorsにドキュメントされている一般的な配列関数やシーケンス関数で、文字列を処理できます。たとえば、文字列内の特定の文字にアクセスしたり変更することができますしかし表示された文字列の幅を計算するために、lengthを使用するべきではないことに注意してください。かわりにstring-widthを使用してください(Size of Displayed Textを参照してください)。

Emacs文字列での非ASCIIにたいすテキスト表現は2つ — ユニバイト(unibyte)とマルチバイト(multibyte)がありますほとんどのLispプログラミングでは、これら2つの表現を気にする必要はありません。詳細は、Text Representationsを参照してください。

キーシーケンスがユニバイト文字列で表されることがあります。ユニバイト文字列がキーシーケンスの場合、範囲128から255までの文字列要素は、範囲128から255の文字コードではなく、メタ文字(これは非常に大きな整数です)を表します。文字列はhyper、super、altで修飾された文字を保持できません。文字列はASCIIコントロール文字を保持できますが、それは他のコントロール文字です。文字列はASCIIコントロール文字の大文字小文字を区別できません。そのような文字をシーケンスに保存したい場合は、文字列ではなくベクターを使用しなければなりません。キーボード入力文字についての情報は、Character Typeを参照してください。

文字列は正規表現を保持するために便利です。string-match (Regular Expression Searchingを参照してください)を使用して、文字列にたいして正規表現をマッチすることもできます。関数match-string (Simple Match Data Accessを参照してください)と、replace-match (see section Replacing the Text that Matched)は、文字列にたいして正規表現をマッチした後に、文字列を分解、変更するのに便利です。

バッファーのように、文字列は文字列内の文字自身と、その文字にたいするテキストプロパティーを含みます。Text Propertiesを参照してください。文字列からバッファーや他の文字列にテキストをコピーする、すべてのLispプリミティブ(Lisp primitives)は、コピーされる文字のプロパティーもコピーします。

文字列を表示したり、バッファーにコピーする関数についての情報は、Textを参照してください。文字または文字列の構文についての情報は、Character TypeString Typeを参照してください。異なるテキスト表現間で変換したり、文字コードをエンコード、デコードする関数については、Non-ASCII Charactersを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 Predicates for Strings

一般的なシーケンスや配列にたいする述語についての情報は、Sequences, Arrays, and Vectors、およびArraysを参照してください。

Function: stringp object

この関数はobjectが文字列の場合はt、それ以外はnilをreturnします。

Function: string-or-null-p object

この関数は、objectが文字列またはnilの場合はt、それ以外はnilをreturnします。

Function: char-or-string-p object

この関数は、objectが文字列または文字(たとえば整数)の場合はt、それ以外はnilをreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 Creating Strings

以下の関数は、新たに文字列を作成したり、文字列同士を結合して文字列を作成したり、文字列の一部から文字列を作成する関数です。

Function: make-string count character

この関数は、charactercount回繰り返すことにより作成された文字列をreturnします。countが負の場合は、エラーをシグナルします。

(make-string 5 ?x)
     ⇒ "xxxxx"
(make-string 0 ?x)
     ⇒ ""

この関数に対応する他の関数にはmake-vector (Vectorsを参照してください)、およびmake-list (Building Cons Cells and Listsを参照してください)が含まれます。

Function: string &rest characters

この関数は、文字charactersを含む文字列をreturnします。

(string ?a ?b ?c)
     ⇒ "abc"
Function: substring string start &optional end

この関数は、stringから、インデックスstartの文字(その文字を含む)から、endまでの文字(その文字は含まない)の範囲の文字から構成される、新しい文字列をreturnします。文字列の最初の文字がインデックス0になります。

(substring "abcdefg" 0 3)
     ⇒ "abc"

上記の例では、‘a’のインデックスは0、‘b’のインデックスは1、‘c’のインデックスは2です。インデックス3 — この文字列の4番目の文字 — は、部分文字列がコピーされる文字位置までをマークします。したがって文字列"abcdefg"から、‘abc’がコピーされます。

負のかすは、文字列の最後から数えることを意味するので、-1は文字列の最後の文字のインデックスです。たとえば:

(substring "abcdefg" -3 -1)
     ⇒ "ef"

この例では、‘e’のインデックスは-3、‘f’のインデックスは-2、‘g’のインデックスは-1です。したがって、‘e’と‘f’が含まれ、‘g’は含まれません。

endnilが使用された場合、それは文字列の長さを意味します。したがって、

(substring "abcdefg" -3 nil)
     ⇒ "efg"

引数endを省略した場合、それはnilを指定したのと同じです。(substring string 0)は、stringのすべてをコピーしてreturnします。

(substring "abcdefg" 0)
     ⇒ "abcdefg"

しかし、この目的のためにはcopy-sequenceを推奨します(see section Sequences)。

stringからコピーされた文字がテキストプロパティーをもつ場合、そのプロパティーは新しい文字列へもコピーされます。Text Propertiesを参照してください。

substringの最初の引数にはベクターも指定できます。たとえば:

(substring [a b (c) "d"] 1 3)
     ⇒ [b (c)]

startが整数でない場合、またはendが整数でもnilでもない場合は、wrong-type-argumentエラーがシグナルされます。startendの後の文字を指す場合、またはstringにたいして範囲外の整数をどちらかに指定した場合は、args-out-of-rangeエラーがシグナルされます。

この関数に対応するのはbuffer-substring (Examining Buffer Contentsを参照してください)で、これはカレントバッファー内のテキストの一部を含む文字列をreturnします。文字列の先頭はインデックス0ですが、バッファーの先頭はインデックス1です。

Function: substring-no-properties string &optional start end

これはsubstringと同じようにL機能しますが、値からすべてのテキストプロパティーを破棄します。startを省略したり、nilを指定することができ、この場合0に等しくなります。したがって(substring-no-properties string)は、すべてのテキストプロパティーが削除されたstringのコピーをreturnします。

Function: concat &rest sequences

この関数は、渡された引数内の文字からなる、新しい文字列をreturnします(もしあればテキストプロパティーも)。引数には文字列、数のリスト、数のベクターを指定できます。引数は変更されません。concatに引数を指定しない場合、空文字列をreturnします。

(concat "abc" "-def")
     ⇒ "abc-def"
(concat "abc" (list 120 121) [122])
     ⇒ "abcxyz"
;; nilhあ空のシーケンス。
(concat "abc" nil "-def")
     ⇒ "abc-def"
(concat "The " "quick brown " "fox.")
     ⇒ "The quick brown fox."
(concat)
     ⇒ ""

この関数は常に、任意の既存の文字列にたいしてeqではない、新しい文字列を構築しますが、結果が空文字列の時は例外です(スペースを省くために、Emacsは空のマルチバイト文字列を1つだけ作成します)。

他の結合関数(concatenation functions)についての情報は、Mapping FunctionsmapconcatFunctions for VectorsvconcatBuilding Cons Cells and Listsappendを参照してください。シェルコマンドで使用される文字列の中に、個々のコマンドライン引数を結合するには、combine-and-quote-stringsを参照してください。

Function: split-string string &optional separators omit-nulls trim

この関数は、正規表現separators(Regular Expressionsを参照してください)にもとづいて、stringを部分文字列に分解します。separatorsにたいする各マッチは、分割位置を定義します。分割位置の間にある部分文字列を、リストにまとめてreturnします。

omit-nullsnil(または省略)の場合、連続する2つのseparatorsへのマッチ、またはstringの最初か最後にマッチしたときの空文字列が結果に含まれます。omit-nullstの場合、これらの空文字列は結果から除外されます。

separatorsnil(または省略)の場合、デフォルトはsplit-string-default-separatorsの値になります。

特別なケースとして、separatorsnil(または省略)の場合、常に結果から空文字列が除外されます。したがって:

(split-string "  two words ")
     ⇒ ("two" "words")

結果は、ほとんど有用ではないであろう("" "two" "words" "")という結果ではありません。このような結果が必要な時は、separatorsに明示的な値を使用します:

(split-string "  two words "
              split-string-default-separators)
     ⇒ ("" "two" "words" "")

他にも例を示します:

(split-string "Soup is good food" "o")
     ⇒ ("S" "up is g" "" "d f" "" "d")
(split-string "Soup is good food" "o" t)
     ⇒ ("S" "up is g" "d f" "d")
(split-string "Soup is good food" "o+")
     ⇒ ("S" "up is g" "d f" "d")

空のマッチはカウントされます。例外は、空でないマッチを使用することにより、すでに文字列の最後に到達しているとき、またはstringが空の時で、この場合split-stringは最後の空マッチを探しません。

(split-string "aooob" "o*")
     ⇒ ("" "a" "" "b" "")
(split-string "ooaboo" "o*")
     ⇒ ("" "" "a" "b" "")
(split-string "" "")
     ⇒ ("")

しかし、separatorsが空文字列にマッチできるとき、通常はomit-nullstにすれば、前の3つの例の不明瞭さは、ほとんど発生しません:

(split-string "Soup is good food" "o*" t)
     ⇒ ("S" "u" "p" " " "i" "s" " " "g" "d" " " "f" "d")
(split-string "Nice doggy!" "" t)
     ⇒ ("N" "i" "c" "e" " " "d" "o" "g" "g" "y" "!")
(split-string "" "" t)
     ⇒ nil

空でないマッチより空のマッチを優先するような、一部の“非貪欲(non-greedy)”な値をseparatorsに指定することにより、幾分奇妙(しかし予見可能)な振る舞いが発生する場合があります。繰り返しますが、そのような値は実際にはまれです:

(split-string "ooo" "o*" t)
     ⇒ nil
(split-string "ooo" "\\|o+" t)
     ⇒ ("o" "o" "o")

オプションの引数trimが非nilの場合、その値は各部分文字列の最初と最後からトリムするテキストにマッチする正規表現を指定します。トリムにより、その部分文字列が空になるような場合、それは空文字列として扱われます。

文字列を分割して、call-processstart-processに適した、個々のコマンドライン引数のリストにする必要がある場合は、split-string-and-unquoteを参照してください。

Variable: split-string-default-separators

split-stringseparatorsにたいするデフォルト値です。通常の値は、"[ \f\t\n\r\v]+"です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 Modifying Strings

既存の文字列の内容を変更するもっとも基本的な方法は、aset (see section Functions that Operate on Arrays)を使用する方法です。(aset string idx char)は、stringのインデックスidxに、charを格納します。それぞれの文字は1文字以上を占有しますが、すでにインデックスの場所にある文字のバイト数が、charが要するバイト数と異なる場合、asetはエラーをシグナルします。

より強力な関数はstore-substringです:

Function: store-substring string idx obj

この関数は、インデックスidxで開始される位置にobjを格納することにより、文字列stringの内容の一部を変更します。objは文字、または(stringより小さい)文字列です。

既存の文字列の長さを変更するのは不可能なので、stringの実際の長さにobjが収まらない場合、またはstringのその位置に現在ある文字のバイト数が、新しい文字に必要なバイト数と異なる場合はエラーになります。

パスワードを含む文字列をクリアーするときは、clear-stringを使用します:

Function: clear-string string

これはstringをユニバイト文字列として、内容を0にクリアーします。これによりstringの長さも変更されるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 Comparison of Characters and Strings

Function: char-equal character1 character2

この関数は引数が同じ文字を表す場合はt、それ以外はnilをreturnします。case-fold-searchが非nilの場合、この関数は大文字小文字の違いを無視します。

(char-equal ?x ?x)
     ⇒ t
(let ((case-fold-search nil))
  (char-equal ?x ?X))
     ⇒ nil
Function: string= string1 string2

この関数は、2つの文字列の文字が正確にマッチする場合は、tをreturnします。引数にシンボルを指定することもでき、この場合はシンボル名が使用されます。case-fold-searchとは無関係に、大文字小文字は常に意味をもちます。

この関数は、equalで2つの文字列を比較するのと等価です(Equality Predicatesを参照してください)。特に、2つの文字列のテキストプロパティーは無視されます。テキストプロパティーだけが異なる文字列を区別する必要がある場合は、equal-including-propertiesを使用します。しかしequalとは異なり、どちらかの引数が文字列でもシンボルでもない場合、string=はエラーをシグナルします。

(string= "abc" "abc")
     ⇒ t
(string= "abc" "ABC")
     ⇒ nil
(string= "ab" "ABC")
     ⇒ nil

技術的な理由により、ユニバイト文字列とマルチバイト文字列がequalなのは、それらが同じ文字コードのシーケンスを含み、それらすべてのコードが0から127(ASCII)か、160から255(eight-bit-graphic)のときだけです。しかしユニバイト文字列をマルチバイト文字列に変更する際、コードが160から255の範囲にあるすべての文字はより高いコードに変換され、ASCII文字は変換されないまま残ります。したがってユニバイト文字列と、それを変換したマルチバイト文字列は、その文字列のすべてがASCIIのときだけequalです。マルチバイト文字列中で、もし文字コード160から255の文字があったとしても、それは完全に正しいとは言えません。結果として、すべてがASCIIではないユニバイト文字列とマルチバイト文字列がequalであるという状況は、もしかしたらEmacs Lispプロプラマーが直面するかもしれない、とても希少な偽術的に不可解な状況だといえます。Text Representationsを参照してください。

Function: string-equal string1 string2

string-equalstring=に対する別名です。

Function: string< string1 string2

この関数は、2つの文字列を1文字づつ比較します。この関数は、同時に2つの文字列をスキャンして、対応する文字同士がマッチしない最初のペアを探します。2つの文字列内で、小さいほうの文字がstring1の文字の場合、string1が小さいことになり、この関数はtをreturnします。小さいほうの文字がstring2の文字の場合、string1が大きいことになり、この関数はnilをreturnします。2つの文字列が完全にマッチした場合、値はnilになります。

文字のペアは、文字コードで比較されます。ASCII文字セットでは、小文字英字は大文字英字より、高い数値をもつことに留意してください。数字および多くの句読点文字は、大文字英字より低い数値をもちます。ASCII文字は、任意の非ASCII文字より小さくなります。ユニバイト非ASCII文字は、任意のマルチバイト非ASCII文字より、常に小さくなります(Text Representationsを参照してください)。

(string< "abc" "abd")
     ⇒ t
(string< "abd" "abc")
     ⇒ nil
(string< "123" "abc")
     ⇒ t

文字列の長さが異なり、string1の長さまでマッチする場合、結果はtになります。string2の長さまでマッチする場合、結果はnilになります。文字を含まない文字列は、他の任意の文字列より小さくなります。

(string< "" "abc")
     ⇒ t
(string< "ab" "abc")
     ⇒ t
(string< "abc" "")
     ⇒ nil
(string< "abc" "ab")
     ⇒ nil
(string< "" "")
     ⇒ nil

引数としてシンボルを指定することもでき、この場合はシンボルのプリント名が使用されます。

Function: string-lessp string1 string2

string-lesspstring<にたいする別名です。

Function: string-prefix-p string1 string2 &optional ignore-case

この関数は、string1string2のプレフィクス(接頭辞)の場合(たとえばstring2string1で始まる場合)、非nilをreturnします。オプションの引数ignore-caseが非nilの場合、比較において大文字小文字の違いは無視されます。

Function: string-suffix-p suffix string &optional ignore-case

この関数は、suffixstringのサフィックス(接尾辞)の場合(たとえばstringsuffixで終わる場合)、非nilをreturnします。オプションの引数ignore-caseが非nilの場合、比較において大文字小文字の違いは無視されます。

Function: compare-strings string1 start1 end1 string2 start2 end2 &optional ignore-case

この関数は、string1の指定された部分を、string2の指定された部分と比較します。string1の指定された部分とは、インデックスstart1(その文字を含む)から、インデックスend1(その文字を含まない)までです。start1nilを指定すると文字列の最初という意味になり、end1nilを指定すると文字列の長さを意味します同様に、string2の指定された部分とは、インデックスstart2からインデックスend2までです。

文字列は、文字列内の文字の数値により比較されます。たとえば、str1str2は、最初に異なる文字でstr1の文字の数値が小さいときに、“小さい”と判断されます。ignore-caseが非nilの場合、文字は比較を行なう前に小文字に変換されます。比較のためにユニバイト文字列はマルチバイト文字列に変換されるので(Text Representationsを参照してください)、ユニバイト文字列と、それを変換したマルチバイト文字列は、常に等しくなります。

2つの文字列の指定された部分がマッチした場合、値はtになります。それ以外では、値は整数で、これは何文字が一致して、どちらの文字が小さいかを示します。この値の絶対値は、2つの文字列の先頭から一致した文字数に1加えた値になります。string1(または指定された部分)のほうが小さい場合、符号は負になります。

Function: assoc-string key alist &optional case-fold

この関数はassocと同様に機能しますが、keyは文字列かシンボルでなければならず、比較はcompare-stringsを使用して行なわれます。テストする前にシンボルは文字列に変換されます。case-foldが非nilの場合、大文字小文字の違いは無視されます。assocとは異なり、この関数はコンスではない文字列またはシンボルのalist要素もマッチできます。特に、alistは実際のalistではなく、文字列またはリストでも可能です。Association Listsを参照してください。

バッファー内のテキストを比較する方法として、Comparing Textの関数compare-buffer-substringsも参照してください。文字列にたいして正規表現のマッチを行なう関数string-matchも、ある種の文字列比較に使用することができます。Regular Expression Searchingを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6 Conversion of Characters and Strings

このセクションでは文字、文字列、整数の間で変換を行なう関数を説明します。format (Formatting Stringsを参照してください)、およびprin1-to-string (Output Functionsを参照してください)も、Lispオブジェクトを文字列に変換できます。read-from-string (Input Functionsを参照してください)は、Lispオブジェクトの文字列表現を、オブジェクトに“変換”できます。関数string-to-multibyteおよびstring-to-unibyteは、テキスト表現を文字列に変換します(Converting Text Representationsを参照してください)。

テキスト文字と一般的なインプットイベントにたいするテキスト説明を生成する関数(single-key-descriptionおよびtext-char-description)については、Documentationを参照してください。これらの関数は主にヘルプメッセージを作成するために使用されます。

Function: number-to-string number

この関数はnumberの10進プリント表現からなる文字列をreturnします。引数が負の場合、return値はマイナス記号から開始されます。

(number-to-string 256)
     ⇒ "256"
(number-to-string -23)
     ⇒ "-23"
(number-to-string -23.5)
     ⇒ "-23.5"

int-to-stringは、この関数にたいする半ば廃れた(semi-obsolete)エイリアスです。

Formatting Stringsの関数formatも参照してください。

Function: string-to-number string &optional base

この関数はstring内の文字の数値的な値をreturnします。baseが非nilの場合、値は2以上16以下でなければならず、整数はその基数に変換されます。basenilの場合、基数に10が使用されます。浮動少数の変換は基数が10のときだけ機能します。わたしたちは浮動小数点数にたいして他の基数を実装していません。なえならこれには多くの作業が必要で、その割にその機能が有用には思えないからです。stringが整数のように見えるが、その値がLispの整数に収まらないほど大きな値の場合、string-to-numberは浮動小数の結果をreturnします。

解析ではstringの先頭にあるスペースとタブはスキップして、それから与えられた基数で数字として解釈できるところまでstringを読み取ります(スペースとタブだけではなく、先頭にある他の空白文字を無視するシステムもあります)。stringを数字として解釈できない場合、この関数は0をreturnします。

(string-to-number "256")
     ⇒ 256
(string-to-number "25 is a perfect square.")
     ⇒ 25
(string-to-number "X256")
     ⇒ 0
(string-to-number "-4.5")
     ⇒ -4.5
(string-to-number "1e5")
     ⇒ 100000.0

string-to-intは、この関数にたいする半ば廃れたエイリアスです。

Function: char-to-string character

この関数は、1つの文字characterを含む新しい文字列をreturnします。関数stringのほうがより一般的なので、この関数は半ば廃れています。Creating Stringsを参照してください。

Function: string-to-char string

この関数は、stringの最初の文字をreturnします。これはほとんど(aref string 0)と同じで、例外は文字列が空のときに0をreturnすることです(文字列の最初の文字がASCIIコード0のヌル文字のときも、0をreturnします)。この関数は、残すのに充分なほど有用と思えない場合、将来削除されるかもしれません。

以下は、文字列へ/からの変換に使用できる、その他の関数です:

concat

この関数はベクターまたはリストから文字列に変換します。Creating Stringsを参照してください。

vconcat

この関数は文字列をベクターに変換します。Functions for Vectorsを参照してください。

append

この関数は文字列をリストに変換します。Building Cons Cells and Listsを参照してください。

byte-to-string

この関数は文字データのバイトをユニバイト文字列に変換します。Converting Text Representationsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7 Formatting Strings

フォーマット(formatting)とは、定数文字列内のなまざまな場所を、計算された値で置き換えることにより、文字列を構築することを意味します。この定数文字列は、他の値がプリントされる方法、同様にどこに表示するかを制御します。これはフォーマット文字列(format string)と呼ばれます。

フォーマットは、表示されるメッセージを計算するために便利なことがしばしばあります。実際に、関数messageおよびerrorは、ここで説明する機能と同じフォーマットを提供します。これらの関数とformatの違いは、フォーマットされた結果を使用する方法だけです。

Function: format string &rest objects

この関数は、stringをコピーしてから、対応するobjectsをエンコードする、コピー内の任意のフォーマット指定(format specification)を置換することにより作成される、新しい文字列をreturnします。引数objectsは、フォーマットされる計算された値です。

string内のフォーマット指定以外の文字は、(もしあれば)テキストプロパティーを含め、出力に直接コピーされます。

フォーマット指定は、‘%’で始まる文字シーケンスです。したがってstring内に‘%d’があれば、formatはそれを、フォーマットされる値の1つ(引数objectsのうちの1つ)にたいするプリント表現で置き換えます。たとえば:

(format "The value of fill-column is %d." fill-column)
     ⇒ "The value of fill-column is 72."

formatは文字‘%’をフォーマット指定と解釈するので、決して最初の引数に不定な文字列(arbitrary string)を渡すべきではありません。これは特に何らかのLispコードにより生成された文字列の場合に当てはまります。その文字列が決して文字‘%’を含まないと確信できないときは、以下で説明するように最初の引数に"%s"を渡して、不定な文字列を2番目の引数として渡します:

  (format "%s" arbitrary-string)

stringに複数のフォーマット指定が含まれる場合、フォーマット指定はobjectsから連続して値を引き当てます。つまり、string内の1番目のフォーマット指定は1番目の値、2番目のフォーマット指定は2番目の値、...を使用します。余分なフォーマット指定(対応する値がない場合)は、エラーとなります。フォーマットされる値が余分にある場合は、無視されます。

ある種のフォーマット指定は、特定の型の値を要求します。その要求に適合しない値を与えた場合、エラーがシグナルされます。

以下は有効なフォーマット指定の表です:

%s

フォーマット指定を、クォートなし(つまりprin1ではなくprincを使用して。Output Functionsを参照してください)の、オブジェクトのプリント表現で置き換えます。したがって、文字列は‘"’文字なしの、文字列内容だけが表示され、シンボルは‘\’文字なしで表されます。

オブジェクトが文字列の場合、文字列のプロパティーは出力にコピーされます。‘%s’のテキストプロパティー自身もコピーされますが、オブジェクトのテキストプロパティーが優先されます。

%S

フォーマット指定を、クォートあり(つまりprin1を使用して。Output Functionsを参照してください)の、オブジェクトのプリント表現で置き換えます。したがって、文字列は‘"’文字で囲まれ、必要となる特別文字の前に‘\’文字が表示されます。

%o

フォーマット指定を8進表現の整数で置き換えます。

%d

フォーマット指定を10進表現の整数で置き換えます。

%x
%X

フォーマット指定を16進表現の整数で置き換えます。‘%x’の場合は小文字、‘%X’の場合は大文字が使用されます。

%c

フォーマット指定を、与えられた値の文字で置き換えます。

%e

フォーマット指定を、浮動小数点数の指数表現で置き換えます。

%f

フォーマット指定を、浮動小数点数にたいする10進少数表記で置き換えます。

%g

フォーマット指定を、指数または10進少数のどちらか短いほうの表記を使用した浮動小数点数で置き換えます。

%%

フォーマット指定を1つの‘%’で置き換えます。このフォーマット指定は、値を使用しません。たとえば、(format "%% %d" 30)"% 30"をreturnします。

他のフォーマット文字は、‘Invalid format operation’エラーになります。

以下にいくつかの例を示します:

(format "The name of this buffer is %s." (buffer-name))
     ⇒ "The name of this buffer is strings.texi."

(format "The buffer object prints as %s." (current-buffer))
     ⇒ "The buffer object prints as strings.texi."

(format "The octal value of %d is %o,
         and the hex value is %x." 18 18 18)
     ⇒ "The octal value of 18 is 22,
         and the hex value is 12."

フォーマット指定はフィールド幅(width)をもつことができ、これは‘%’とフォーマット指定文字(specification character)の間の10進の数字です。そのオブジェクトのプリント表現が、このフィールド幅より少ない文字で構成される場合、formatはパディングしてフィールド幅に拡張します。フォーマット指定‘%%’では、フィールド幅の指定は無視されます。シールド幅指定により行なわれるパディングは通常、左側にスペースを挿入します。

(format "%5d is padded on the left with spaces" 123)
     ⇒ "  123 is padded on the left with spaces"

フィールド幅が小さすぎる場合でも、formatはオブジェクトのプリント表現を切り詰めません。したがって、情報を失う危険を犯すことなく、フィールドの最小幅を指定することができます。以下の2つの例では、‘%7s’は最小幅に7を指定します。1番目の例では、‘%7s’に挿入される文字列は3文字だけなので、4つのブランクスペースによりパディングされます。2番目の例では、文字列"specification"は13文字ですが、切り詰めはされません。

(format "The word `%7s' has %d letters in it."
        "foo" (length "foo"))
     ⇒ "The word `    foo' has 3 letters in it."
(format "The word `%7s' has %d letters in it."
        "specification" (length "specification"))
     ⇒ "The word `specification' has 13 letters in it."

%’の直後、オプションのフィールド幅指定の前に、フラグ文字(flag characters)を置くこともできます。

フラグ‘+’は、正数の前にプラス符号を挿入するので、数には常に符号がつきます。フラグとしてスペースを指定すると、正数の前に1つのスペースが挿入されます(それ以外は、正数は最初の数字から開始されます)。これらのフラグは、正数と負数が同じ列数を使用することを確実にするのに便利です。これらは‘%d’、‘%e’、‘%f’、‘%g’以外では無視され、両方が指定された場合は、‘+’が優先されます。

フラグ‘#’は“代替形式(alternate form)”を指定し。これは使用するフォーマットに依存します。‘%o’にたいしては、結果を‘0’で開始させます。‘%x’と‘%X’にたいしては、結果のプレフィクスは‘0x’または‘0X’になります。‘%e’、‘%f’、‘%g’にたいしては、‘#’フラグは、少数部が0のときも小数点が含まれることを意味します。

フラグ‘0’は、スペースの代わりに文字‘0’でパディングします。このフラグは‘%s’、‘%S’、‘%c’のような、非数値のフォーマット指定文字では無視されます。もれらのフォーマット指定文字で‘0’フラグを指定できますが、それでもスペースでパディングされます。

フラグ‘-’はフィールド幅指定により挿入されるパディングに作用し、もしパディングがある場合、左側ではなく右側にパディングされます。‘-’と‘0’の両方が指定された場合、‘0’フラグは無視されます。

(format "%06d is padded on the left with zeros" 123)
     ⇒ "000123 is padded on the left with zeros"

(format "%-6d is padded on the right" 123)
     ⇒ "123    is padded on the right"

(format "The word `%-7s' actually has %d letters in it."
        "foo" (length "foo"))
     ⇒ "The word `foo    ' actually has 3 letters in it."

すべてのフォーマット指定文字には、その文字の前(フィールド幅がある場合は、その後)に、オプションで精度(precision)を指定できます。精度は小数点‘.’と、その後に桁文字列(digit-string)を指定します。浮動少数のフォーマット指定(‘%e’、‘%f’、‘%g’)では、精度は表示する小数点以下の桁数を指定します。0の場合は小数点も省略されます。‘%s’と‘%S’にたいしては、文字列を精度で指定された幅に切り詰めます。したがって‘%.3s’では、objectにたいするプリント表現の最初の3文字だけが表示されます。他のフォーマット指定文字にたいしては、精度は効果がありません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8 Case Conversion in Lisp

大文字小文字変換関数(character case functions)は、1つの文字または文字列の内容の大文字小文字を変換します。関数は通常、アルファベット文字(英字‘A’から‘Z’と‘a’から‘z’、同様に非ASCIIの英字)だけを変換し、それ以外の文字は変換しません。大文字小文字テーブル(case table。The Case Tableを参照してください)で指定することにより大文字小文字の変換に異なるマッピングを指定できます。

これらの関数は、引数として渡された文字列は変更しません。

以下の例では文字‘X’と‘x’を使用し、これらのASCIIコードは88と120です。

Function: downcase string-or-char

この関数は、string-or-char(文字か文字列)を小文字に変換します。

string-or-charが文字列の場合、この関数は引数の大文字を小文字に変換した、新しい文字列をreturnします。string-or-charが文字の場合、この関数は対応する小文字(正数)をreturnします。元の文字が小文字の場合、または英字でない場合、return値は元の文字と同じです。

(downcase "The cat in the hat")
     ⇒ "the cat in the hat"

(downcase ?X)
     ⇒ 120
Function: upcase string-or-char

この関数は、string-or-char(文字か文字列)を大文字に変換します。

string-or-charが文字列の場合、この関数は引数の小文字を大文字に変換した、新しい文字列をreturnします。string-or-charが文字の場合、この関数は対応する大文字(正数)をreturnします。元の文字が大文字の場合、または英字でない場合、return値は元の文字と同じです。

(upcase "The cat in the hat")
     ⇒ "THE CAT IN THE HAT"

(upcase ?x)
     ⇒ 88
Function: capitalize string-or-char

この関数は文字列または文字をキャピタライズ(capitalize: 先頭が大文字で残りは小文字)します。この関数は、string-or-charが文字列の場合、string-or-charの各単語がキャピタライズされた新しいコピーをreturnします。これは各単語の最初の文字が大文字に変換され、残りは小文字に変換されることを意味します。

単語の定義は、カレント構文テーブル(current syntax table)の単語構成構文クラス(word constituent syntax class)に割り当てられた、連続する文字の任意シーケンスです(Table of Syntax Classesを参照してください)。

string-or-charが文字の場合、この関数はupcaseと同じことを行ないます。

(capitalize "The cat in the hat")
     ⇒ "The Cat In The Hat"

(capitalize "THE 77TH-HATTED CAT")
     ⇒ "The 77th-Hatted Cat"

(capitalize ?x)
     ⇒ 88
Function: upcase-initials string-or-char

この関数は、string-or-charが文字列の場合、string-or-charの中の単語の頭文字をキャピタライズし、頭文字以外の文字は変更しません。この関数は、string-or-charの各単語の頭文字が大文字に変換された新しいコピーをreturnします。

単語の定義は、カレント構文テーブル(current syntax table)の単語構成構文クラス(word constituent syntax class)に割り当てられた、連続する文字の任意シーケンスです(Table of Syntax Classesを参照してください)。

upcase-initialsの引数が文字の場合、upcase-initialsの結果はupcaseと同じになります。

(upcase-initials "The CAT in the hAt")
     ⇒ "The CAT In The HAt"

文字列を比較する関数(大文字小文字の違いを無視するものや、オプションで大文字小文字の違いを無視できるもの)については、Comparison of Characters and Stringsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.9 The Case Table

特別な大文字小文字テーブル(case table)をインストールすることにより、大文字小文字の変換をカスタマイズできます。大文字小文字テーブルは大文字と小文字の間のマッピングを指定します。大文字小文字テーブルはLispオブジェクトにたいする大文字小文字変換関数(前のセクションを参照してください)と、バッファー内のテキストに適用される関数の両方に影響します。それぞれのバッファーには大文字小文字テーブルがあります。新しいバッファーの大文字小文字テーブルを初期化するために使用される、標準の大文字小文字テーブル(standard case table)もあります。

大文字小文字テーブルは、サブタイプがcase-tableの文字テーブル(char-table。Char-Tablesを参照してください)です。この文字テーブルは、それぞれの文字を対応する小文字にマップします。大文字小文字テーブルは、関連するテーブルを保持する、3つの追加スロットをもちます:

upcase

upcase(大文字)テーブルは、それぞれの文字を対応する大文字にマップします。

canonicalize

canonicalize(正準化)テーブルは、大文字小文字に関連する文字セットのすべてを、その文字セットの特別なメンバーにマップします。

equivalences

equivalence(同値)テーブルは、大の字小文字に関連した文字セットのそれぞれを、そのセットの次の文字にマップします。

単純な例では、小文字へのマッピングを指定することだけが必要です。3つの関連するテーブルは、このマッピングから自動的に計算されます。

大文字と小文字が1対1で対応しない言語もいくつかあります。これらの言語では、2つの異なる小文字が、同じ大文字にマップされます。このような場合、大文字と小文字の両方にたいするマップを指定する必要があります。

追加のcanonicalizeテーブルは、それぞれの文字を、正準化された等価文字にマップします。大文字小文字に関連する任意の2文字は、同じ正準等価文字(canonical equivalent character)をもちます。たとえば‘a’と‘A’は大文字小文字変換に関係があるので、これらの文字は同じ正準等価文字(両方の文字が‘a’、または両方の文字が‘A’)をもつべきです。

追加のequivalencesテーブルは、各等価クラスの文字(同じ正準等価文字をもつ文字)を循環的にマップします(通常のASCIIでは、これは‘a’を‘A’に‘A’を‘a’にマップし、他の等価文字セットにたいしても同様にマップします)。

大文字小文字テーブルを構築する際は、canonicalizenilを指定できます。この場合、Emacsは大文字と小文字のマッピングで、このスロットを充填します。equivalencesにたいしてnilを指定することもできます。この場合、Emacsはcanonicalizeから、このスロットを充填します。実際に使用される大文字小文字テーブルでは、これらのコンポーネントは非nilです。canonicalizeを指定せずにequivalencesを指定しないでください。

以下は大文字小文字テーブルに作用する関数です:

Function: case-table-p object

この述語は、objectが有効な大文字小文字テーブルの場合は、非nilをreturnします。

Function: set-standard-case-table table

この関数は、tableを標準大文字小文字テーブルにして、これ以降に作成される任意のバッファーにたいしてこのテーブルが使用されます。

Function: standard-case-table

これは標準大文字小文字テーブル(standard case table)をreturnします。

Function: current-case-table

この関数は、カレントバッファーの大文字小文字テーブルをreturnします。

Function: set-case-table table

これはカレントバッファーの大文字小文字テーブルを、tableにセットします。

Macro: with-case-table table body…

with-case-tableマクロはカレント大文字小文字テーブルを保存してから、tableをカレント大文字小文字テーブルにセットし、その後にbodyフォームを評価してから、最後に大文字小文字テーブルをリストアします。return値は、bodyの最後のフォームの値です。throwまたはエラー(Nonlocal Exitsを参照してください)により異常終了した場合でも、大文字小文字テーブルはリストアされます。

ASCII文字の大文字小文字変換を変更する言語環境(language environment)がいくつかあります。たとえばTurkishの言語環境では、ASCII文字の‘I’にたいする小文字は、Turkishの“dotless i”です。これは、(ASCIIベースのネットワークプロトコル実装のような)ASCIIの通常の大文字小文字変換を要求するコードに干渉する可能性があります。このような場合は、変数ascii-case-tableにたいしてwith-case-tableマクロを使用します。これにより、変更されていないASCII文字セットの大文字小文字テーブルが保存されます。

Variable: ascii-case-table

ASCII文字セットにたいする大文字小文字テーブルです。すべての言語環境セッティングにおいて、これを変更するべきではありません。

以下の3つの関数は、非ASCII文字セットを定義するパッケージにたいして便利なサブルーチンです。これらはcase-tableに指定された大文字小文字テーブルを変更します。これは標準構文テーブルも変更します。Syntax Tablesを参照してください。通常これらの関数は、標準大文字小文字テーブルを変更するために使用されます。

Function: set-case-syntax-pair uc lc case-table

この関数は、対応する文字のペア(一方は大文字、もう一方は小文字)を指定します。

Function: set-case-syntax-delims l r case-table

この関数は文字lrを、大文字小文字不変区切り(case-invariant delimiter)mpマッチングペアにします。

Function: set-case-syntax char syntax case-table

この関数はcharを、構文syntaxの、大文字小文字不変(case-invariant)とします。

Command: describe-buffer-case-table

このコマンドは、カレントバッファーの大文字小文字テーブルの内容にたいする説明を表示します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5 Lists

リスト(list)は0個以上の要素(任意のLispオブジェクト)のシーケンスを表します。リストとベクターの重要な違いは、、2つ以上のリストが、構造の一部を共有できることです。加えて、リスト全体をコピーすることなく、要素の挿入、削除ができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1 Lists and Cons Cells

Lispでのリストは基本データ型ではありません。リストはコンスセル(cons cells)から構築されます(Cons Cell and List Typesを参照してください)。コンスセルは、順序つきペアを表現するデータオブジェクトです。つまり、コンスセルは2つのスロットをもち、それぞれのスロットはLispオブジェクトを保持(holds)、または参照(refers to)します。1つのスロットはCAR、もう1つはCDRです(これらの名前は歴史的なものです。Cons Cell and List Typesを参照してください)。CDRは“could-er(クダー)”と発音されます。

わたしたちは、コンスセルのCARスロットに現在保持されているオブジェクトが何であれ、“このコンスセルのCARは、...”のような言い方をします。これはCDRの場合も同様です。

リストとは、“互いにつながった(chained together)”一連のコンスセルであり、各セルは次のセルを参照します。リストの各要素にたいして、それぞれ1つのコンスセルがあります。慣例により、コンスセルのCARはリストの要素を保持し、CDRはリストをチェーンするのに使用されます(CARCDRの間の非対称性は完全に慣例的なものです。コンスセルのレベルでは、CARスロットとCDRスロットは同じようなプロパティーをもちます)。したがって、リスト内の各コンスセルのCDRスロットは、次のコンスセルを参照します。

これも慣例的なものですが、リスト内の最後のコンスセルのCDRnilです。わたしたちは、このようなnilで終端された構造を、真リスト(true list)と呼びます。Emacs Lispでは、シンボルnilは、シンボルであり、要素なしのリストでもあります。便宜上、シンボルnilは、そのCDR(およびCAR)にnilをもつと考えます。

したがって真リストのCDRは、常に真リストです。空でない真リストのCDRは、1番目の要素以外を含む真リストです。

リストの最後のコンスセルのCDRnil以外の何らかの値の場合、このリストのプリント表現はドットペア表記(dotted pair notation。Dotted Pair Notationを参照してください)を使用するので、わたしたちはこの構造をドットリスト(dotted list)と呼びます。他の可能性もあります。あるコンスセルのCDRが、そのリストのそれより前にある要素を指すかもしれません。わたしたちは、この構造を循環リスト(circular list)と呼びます。

ある目的にたいしては、そのリストが真リストか、循環リストなのか、ドットリストなのかが問題にならない場合もあります。そのプログラムが、リストを充分に下って最後のコンスセルのCDRを確認しようとしないなら、これは問題になりません。しかし、リストを処理するの関数のいくつかは、真リストを要求し、ドットリストの場合はエラーをシグナルします。リストの最後を探そうと試みる関数のほとんどは、循環リストを与えると無限ループに突入します。

ほとんどのコンスセルはリストの一部として使用されるので、わたしたちはコンスセルで構成される任意の構造を、リスト構造(list structure)と呼びます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.2 Predicates on Lists

以下の述語は、あるLispオブジェクトがアトムなのか、コンスセルなのか、それともリストなのか、またはオブジェクトがnilかどうかテストします(これらの述語の多くは、他の述語で定義することもできますが、多用されるので、定義する価値があるのです)。

Function: consp object

この関数は、objectがコンスセルの場合はt、それ以外はnilをreturnします。たとえnilはリストですが、コンスセルではありません。

Function: atom object

この関数は、objectがアトムの場合はt、それ以外はnilをreturnします。シンボルnilはアトムであり、リストでもあります。そのようなLispオブジェクトはnilだけです。

(atom object) ≡ (not (consp object))
Function: listp object

この関数は、objectがコンスセルかnilの場合はtをreturnします。それ以外はnilをreturnします。

(listp '(1))
     ⇒ t
(listp '())
     ⇒ t
Function: nlistp object

この関数はlistpの反対です。objectがリストでない場合はtをreturnします。それ以外はnilをreturnします。

(listp object) ≡ (not (nlistp object))
Function: null object

この関数は、objectnilの場合はt、それ以外はnilをreturnします。この関数はnotと等価ですが、明解にするために、objectをリストだと考えるときはnull、真偽値だと考えるときはnotを使用します(Constructs for Combining Conditionsnotを参照してください)。

(null '(1))
     ⇒ nil
(null '())
     ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.3 Accessing Elements of Lists

Function: car cons-cell

この関数は、コンスセルcons-cellの1番目のスロットにより参照される値をreturnします。他の言い方をすると、この関数はcons-cellCARをreturnします。

特別なケースとして、cons-cellnilの場合、この関数はnilをreturnします。したがって、リストはすべて引数として有効です。引数がコンスセルでもnilでもない場合、エラーがシグナルされます。

(car '(a b c))
     ⇒ a
(car '())
     ⇒ nil
Function: cdr cons-cell

この関数は、コンスセルcons-cellの2番目のスロットにより参照される値をreturnします。他の言い方をすると、この関数はcons-cellCDRをreturnします。

特別なケースとして、cons-cellnilの場合、この関数はnilをreturnします。したがって、リストはすべて引数として有効です。引数がコンスセルでもnilでもない場合、エラーがシグナルされます。

(cdr '(a b c))
     ⇒ (b c)
(cdr '())
     ⇒ nil
Function: car-safe object

この関数により、他のデータ型によるエラーを起こさずに、コンスセルのCARを取得できます。この関数は、objectがコンスセルの場合はobjectCAR、それ以外はnilをreturnします。この関数は、objectがリスとでないときはエラーをシグナルするcarとは対象的です。

(car-safe object)
≡
(let ((x object))
  (if (consp x)
      (car x)
    nil))
Function: cdr-safe object

この関数により、他のデータ型によるエラーを起こさずに、コンスセルのCDRを取得できます。この関数は、objectがコンスセルの場合はobjectCDR、それ以外はnilをreturnします。この関数は、objectがリスとでないときはエラーをシグナルするcdrとは対象的です。

(cdr-safe object)
≡
(let ((x object))
  (if (consp x)
      (cdr x)
    nil))
Macro: pop listname

このマクロはリストのCARを調べて、それをリストから取り去るのを1度に行なう便利な方法を提供します。この関数はlistnameに格納されたリストにたいして処理を行ないます。この関数はリストから1番目の要素を削除して、CDRlistnameに保存し、その後で削除した要素をreturnします。

1番単純なケースは、リストに名前をつけるためのクォートされていないシンボルの場合です。この場合、このマクロは(prog1 (car listname) (setq listname (cdr listname)))と等価です。

x
     ⇒ (a b c)
(pop x)
     ⇒ a
x
     ⇒ (b c)

より一般的なのは、listnameが汎変数(generalized variable)の場合です。この場合、このマクロはsetfを使用してlistnameに保存します。Generalized Variablesを参照してください。

リストに要素を追加するpushマクロについては、Modifying List Variablesを参照してください。

Function: nth n list

この関数は、listn番目の要素をreturnします。要素は0から数えられるので、listCARは要素0になります。listの長さがn以下の場合、値はnilです。

(nth 2 '(1 2 3 4))
     ⇒ 3
(nth 10 '(1 2 3 4))
     ⇒ nil

(nth n x) ≡ (car (nthcdr n x))

関数eltは似ていますが、これは任意の種類のシーケンスに適用されます。歴史的な理由により、この関数は逆の順序で引数を受け取ります。Sequencesを参照してください。

Function: nthcdr n list

この関数は、listn番目のCDRをreturnします。他の言い方をすると、この関数はlistの最初のn個のリンクをスキップしてから、それ以降をreturnします。

nが0の場合、nthcdrlist全体をreturnします。listの長さがn以下の場合、nthcdrnilをreturnします。

(nthcdr 1 '(1 2 3 4))
     ⇒ (2 3 4)
(nthcdr 10 '(1 2 3 4))
     ⇒ nil
(nthcdr 0 '(1 2 3 4))
     ⇒ (1 2 3 4)
Function: last list &optional n

この関数は、listの最後のリンクをreturnします。このリンクのcarは、このリストの最後の要素です。listがnullの場合、nilがreturnされます。nが非nilの場合、n番目から最後までのリンクがreturnされます。nlistの長さより大きい場合は、list全体がreturnされます。

Function: safe-length list

この関数は、エラーや無限ループの危険なしで、listの長さをreturnします。この関数は一般的に、リスト内のコンスセルの個数をreturnします。しかし循環リストでは、単に上限値が値となるため、非常に大きくなる場合があります。

listnilでもコンスセルでもない場合、safe-lengthは0をreturnします。

循環リストを考慮しなくてもよい場合に、リストの長さを計算するもっとも一般的な方法は、lengthを使うことです。Sequencesを参照してください。

Function: caar cons-cell

これは、(car (car cons-cell))と同じです。

Function: cadr cons-cell

これは、(car (cdr cons-cell))または(nth 1 cons-cell)と同じです。

Function: cdar cons-cell

これは、(cdr (car cons-cell))と同じです。

Function: cddr cons-cell

これは、(cdr (cdr cons-cell))または(nthcdr 2 cons-cell)と同じです。

Function: butlast x &optional n

この関数は、リストxから、最後の要素、または最後のn個の要素を削除してreturnします。nが0より大きい場合、この関数はリストのコピーを作成するので、元のリストに影響はありません。一般的に、(append (butlast x n) (last x n))は、xと等しいリストをreturnします。

Function: nbutlast x &optional n

この関数は、リストのコピーを作成するのではなく、cdrを適切な要素に変更することにより破壊的に機能するバージョンのbutlastです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.4 Building Cons Cells and Lists

リストはLispの核にあるので、リストを構築する多くの関数があります。consはリストを構築する基本的な関数です。しかしEmacsのソースコードでは、consよりlistのほうが多く使用されているのは興味深いことです。

Function: cons object1 object2

この関数は、新しいリスト構造を構築するための、もっとも基本的な関数です。この関数は、object1CARobject2CDRとする、新しいコンスセルを作成して、それから新しいコンスセルをreturnします。引数object1object2は、任意のLispオブジェクトを指定できますが、ほとんどの場合、object2はリストです。

(cons 1 '(2))
     ⇒ (1 2)
(cons 1 '())
     ⇒ (1)
(cons 1 2)
     ⇒ (1 . 2)

リストの先頭に1つの要素を追加するために、consがよく使用されます。これは、リストに要素をコンスすると言います。2たとえば:

(setq list (cons newelt list))

この例で使用されているlistという名前の変数と、以下で説明するlistという名前の関数は、競合しないことに注意してください。任意のシンボルは、両方の役割を果たすことができます。

Function: list &rest objects

この関数は、objectsを要素とするリストを作成します。結果となるリストは、常にnil終端されます。objectsを指定しない場合、空リストがreturnされます。

(list 1 2 3 4 5)
     ⇒ (1 2 3 4 5)
(list 1 2 '(3 4 5) 'foo)
     ⇒ (1 2 (3 4 5) foo)
(list)
     ⇒ nil
Function: make-list length object

この関数は、各要素がobjectの、length個の要素からなるリストを作成します。make-listmake-string(Creating Stringsを参照してください)を比較してみてください。

(make-list 3 'pigs)
     ⇒ (pigs pigs pigs)
(make-list 0 'pigs)
     ⇒ nil
(setq l (make-list 3 '(a b)))
     ⇒ ((a b) (a b) (a b))
(eq (car l) (cadr l))
     ⇒ t
Function: append &rest sequences

この関数は、sequencesのすべての要素を服務リストをreturnします。sequencesには、リスト、ベクター、ブールベクター、文字列も指定できますが、通常は最後にリストを指定するべきです。最後の引数を除くすべての引数はコピーされるので、変更される引数はありません(コピーを行なわずにリストを結合する方法については、Functions that Rearrange Listsnconcを参照してください)。

より一般的には、appendにたいする最後の引数は、任意のLispオブジェクトかもしれません。最後の引数は、コピーまたは変換されません。最後の引数は、新しいリストの最後のコンスセルのCDRになります。最後の引数もリストならば、このリストの要素は、実質的には結果リストの要素になります。最後の要素がリストでない場合、最後のCDRが(真リストで要求される)nilではないので、結果はドットリストになります。

以下はappendを使用した例です:

(setq trees '(pine oak))
     ⇒ (pine oak)
(setq more-trees (append '(maple birch) trees))
     ⇒ (maple birch pine oak)

trees
     ⇒ (pine oak)
more-trees
     ⇒ (maple birch pine oak)
(eq trees (cdr (cdr more-trees)))
     ⇒ t

appendがどのように機能するか、ボックスダイアグラムで見ることができます。変数treesはリスト(pine oak)にセットされ、それから変数more-treesにリスト(maple birch pine oak)がセットされます。しかし変数treesは継続して元のリストを参照します:

more-trees                trees
|                           |
|     --- ---      --- ---   -> --- ---      --- ---
 --> |   |   |--> |   |   |--> |   |   |--> |   |   |--> nil
      --- ---      --- ---      --- ---      --- ---
       |            |            |            |
       |            |            |            |
        --> maple    -->birch     --> pine     --> oak

空のシーケンスは、appendによりreturnされる値に寄与しません。この結果、最後の引数にnilを指定すると、それより前の引数のコピーを強制することになります。

trees
     ⇒ (pine oak)
(setq wood (append trees nil))
     ⇒ (pine oak)
wood
     ⇒ (pine oak)
(eq wood trees)
     ⇒ nil

これは関数copy-sequenceが導入される以前は、リストをコピーする通常の方法でした。Sequences, Arrays, and Vectorsを参照してください。

以下は、appendの引数としてベクターと文字列を使用する例です:

(append [a b] "cd" nil)
     ⇒ (a b 99 100)

apply (Calling Functionsを参照してください)の助けを借りることにより、リストのリストの中の、すべてのリストをappendできます。

(apply 'append '((a b c) nil (x y z) nil))
     ⇒ (a b c x y z)

sequencesが与えられない場合、nilがreturnされます:

(append)
     ⇒ nil

以下は、最後の引数がリストでない場合の例です:

(append '(x y) 'z)
     ⇒ (x y . z)
(append '(x y) [z])
     ⇒ (x y . [z])

2番目の例は、最後の引数はシーケンスですがリスとではない場合で、このシーケンスの要素は、結果リストの要素にはなりません。かわりに、最後の引数がリストでないときと同様、シーケンスが最後のCDRになります。

Function: reverse list

この関数は、要素はlistの要素ですが、順序が逆の新しいリストを作成します。元の引数listは、変更されません

(setq x '(1 2 3 4))
     ⇒ (1 2 3 4)
(reverse x)
     ⇒ (4 3 2 1)
x
     ⇒ (1 2 3 4)
Function: copy-tree tree &optional vecp

この関数はツリーtreeのコピーをreturnします。treeがコンスセルの場合、同じCARCDRをもつ新しいコンスセルを作成してから、同じ方法によりCARCDRを再帰的にコピーします。

通常、treeがコンスセル以外の場合、copy-treeは単にtreeをreturnします。しかし、vecpが非nilの場合、この関数はベクターでもコピーします(そしてベクターの要素を再帰的に処理します)。

Function: number-sequence from &optional to separation

これは、fromからseparationづつインクリメントして、toの直前で終わる、数字のリストをreturnします。separationには正または負の数を指定でき、デフォルトは1です。tonil、または数的にfromと等しい場合、値は1要素のリスト(from)になります。separationが正でtofromより小さい場合、またはseparationが負でtofromより大きい場合、これらの引数は空のシーケンスを指示することになるので、値はnilになります。

separationが0で、tonilでもなく、数的にfromとも等しくない場合、これらの引数は無限シーケンスを指示することになるので、エラーがシグナルされます。

引数はすべて数字です。浮動少数の計算は正確ではないので、浮動少数の引数には用心する必要があります。たとえばマシンに依存して、(number-sequence 0.4 0.8 0.2)が3要素のリストをreturnするのに、(number-sequence 0.4 0.6 0.2)が1要素のリスト(0.4)をreturnすることがよく起こります。リストのn番目の要素は、厳密に(+ from (* n separation))という式により計算されます。したがって、リストに確実にtoが含まれるようにするには、この式に適切な型のtoを渡すことができます。別の方法として、toを少しだけ大きな値(separationが負の場合は、少しだけ小さな値)に置き換えることもできます。

いくつか例を示します:

(number-sequence 4 9)
     ⇒ (4 5 6 7 8 9)
(number-sequence 9 4 -1)
     ⇒ (9 8 7 6 5 4)
(number-sequence 9 4 -2)
     ⇒ (9 7 5)
(number-sequence 8)
     ⇒ (8)
(number-sequence 8 5)
     ⇒ nil
(number-sequence 5 8 -1)
     ⇒ nil
(number-sequence 1.5 6 2)
     ⇒ (1.5 3.5 5.5)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.5 Modifying List Variables

これらの関数、および1つのマクロは、変数に格納されたリストを変更する便利な方法を提供します。

Macro: push element listname

このマクロは、CARelementで、CDRlistnameで指定されたリストであるような新しいリストを作成して、そのリストをlistnameに保存します。単純なのは、listnameはリストに名前をつけるクォートされていないシンボルのときで、この場合マクロは(setq listname (cons element listname))と等価です。

(setq l '(a b))
     ⇒ (a b)
(push 'c l)
     ⇒ (c a b)
l
     ⇒ (c a b)

より一般的なのは、listnameが汎変数の場合です。この場合、このマクロは(setf listname (cons element listname))と等価です。Generalized Variablesを参照してください。

リストから1番目の要素を取り出すpopマクロについては、Accessing Elements of Listsを参照してください。

以下の2つの関数は、変数の値であるリストを変更します。

Function: add-to-list symbol element &optional append compare-fn

この関数は、elementsymbolの値のメンバーでない場合は、symbolelementをコンスすることにより、変数symbolをセットします。この関数は、リストが更新されているかに関わらず、結果のリストをreturnしますsymbolの値は、呼び出し前にすでにリストであることが望ましいです。elementがリストの既存メンバーか比較するために、add-to-listcompare-fnを使用します。compare-fnnilの場合は、equalを使用します。

elementが追加される場合は通常、symbolの前に追加されますが、オプションの引数appendが非nilの場合は、最後に追加されます。

引数symbolは、暗黙にクォートされません。setqとは異なり、add-to-listsetのような通常の関数です。クォートしたい場合は自分で引数をクォートします。

以下はadd-to-listを使用する方法をシナリオで示します:

(setq foo '(a b))
     ⇒ (a b)

(add-to-list 'foo 'c)     ;; cを追加。
     ⇒ (c a b)

(add-to-list 'foo 'b)     ;; 効果なし。
     ⇒ (c a b)

foo                       ;; fooが変更された。
     ⇒ (c a b)

以下は(add-to-list 'var value)と等価な式です:

(or (member value var)
    (setq var (cons value var)))
Function: add-to-ordered-list symbol element &optional order

この関数は、古い値(リストでなければなりません)のorderで指定された位置に、elementを挿入することにより、変数symbolをセットします。elementがすでにこのリストのメンバーである場合、リスト内の要素の位置はorderにしたがって調整されます。メンバーかどうかは、eqを使用してテストされます。この関数は、更新されているかどうかに関わらず、結果のリストをreturnします。

orderは通常、数字(正数か浮動小数)で、リストの要素は、その数字の昇順で並べられます。

orderを省略またはnilにすることもできます。これにより、リストにelementがすでに存在する場合、elementの数字順序は変更されません。それ以外では、elementは数字順序をもちません。リストの数字順序をもたない要素は、リストの最後に配され、特別な順序はつきません。

orderに他の値を指定した場合、elementがすでに数字順序をもつときは数字順序が削除されます。それ以外は、nilと同じです。

引数symbolは、暗黙にクォートされません。add-to-ordered-listは、setqなどとは異なり、setのような通常の関数です。必要な場合は引数を自分でクォートしてください。

順序の情報は、symbollist-orderプロパティーのハッシュテーブルに保存されます。

以下にadd-to-ordered-listを使用する方法をシナリオで示します:

(setq foo '())
     ⇒ nil

(add-to-ordered-list 'foo 'a 1)     ;; aを追加。
     ⇒ (a)

(add-to-ordered-list 'foo 'c 3)     ;; cを追加。
     ⇒ (a c)

(add-to-ordered-list 'foo 'b 2)     ;; bを追加。
     ⇒ (a b c)

(add-to-ordered-list 'foo 'b 4)     ;; bを移動。
     ⇒ (a c b)

(add-to-ordered-list 'foo 'd)       ;; dを後に追加。
     ⇒ (a c b d)

(add-to-ordered-list 'foo 'e)       ;; eを追加。
     ⇒ (a c b e d)

foo                       ;; fooが変更された。
     ⇒ (a c b e d)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.6 Modifying Existing List Structure

基本関数setcarおよびsetcdrにより、コンスセルのCARおよびCDRの内容を変更できます。わたしたちは、これらが既存のリスト構造を変更することから、これらを“破壊的”処理と呼びます。

Common Lispに関する注意: Common Lispはリスト構造の変更にrplacaおよびrplacdを使用します。これらはsetcarsetcdrと同じ方法でリスト構造を変更しますが、setcarsetcdrは新しいCARまたはCDRをreturnするのにたいし、Common Lispの関数はコンスセルをreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.6.1 Altering List Elements with setcar

コンスセルのCARの変更は、setcarにより行なわれます。リストにたいして使用された場合、setcarはリストの1つの要素を、他の要素に置き換えます。

Function: setcar cons object

この関数は、以前のCARを置き換えて、consの新しいCARobjectを格納します。他の言い方をすると、この関数はconsCARスロットを、objectを参照するように変更します。この関数は値objectをreturnします。たとえば:

(setq x '(1 2))
     ⇒ (1 2)
(setcar x 4)
     ⇒ 4
x
     ⇒ (4 2)

コンスセルが、複数のリストが共有された構造の一部の場合、コンスに新しいCARを格納することにより、これら共有されたリストの各1つの要素を変更します。以下は例です:

;; 部分的に共有された2つのリストを作成。
(setq x1 '(a b c))
     ⇒ (a b c)
(setq x2 (cons 'z (cdr x1)))
     ⇒ (z b c)

;; 共有されたリンクのCARを置き換え。
(setcar (cdr x1) 'foo)
     ⇒ foo
x1                           ; 両方のリストが変更された。
     ⇒ (a foo c)
x2
     ⇒ (z foo c)

;; 共有されていないリンクのCARを置き換え。
(setcar x1 'baz)
     ⇒ baz
x1                           ; 1つのリストだけが変更された。
     ⇒ (baz foo c)
x2
     ⇒ (z foo c)

なぜbを置き換えると両方が変更されるのかを説明するために、変数x1x2の2つのリストによる共有構造を視覚化してみましょう:

        --- ---        --- ---      --- ---
x1---> |   |   |----> |   |   |--> |   |   |--> nil
        --- ---        --- ---      --- ---
         |        -->   |            |
         |       |      |            |
          --> a  |       --> b        --> c
                 |
       --- ---   |
x2--> |   |   |--
       --- ---
        |
        |
         --> z

同じ関係を別のボックス図で示すと、以下のようになります:

x1:
 --------------       --------------       --------------
| car   | cdr  |     | car   | cdr  |     | car   | cdr  |
|   a   |   o------->|   b   |   o------->|   c   |  nil |
|       |      |  -->|       |      |     |       |      |
 --------------  |    --------------       --------------
                 |
x2:              |
 --------------  |
| car   | cdr  | |
|   z   |   o----
|       |      |
 --------------

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.6.2 Altering the CDR of a List

CDRを変更するもっとも低レベルの基本関数は、setcdrです:

Function: setcdr cons object

この関数は前のCDRを置き換えて、consの新しいCDRobjectを格納します。他の言い方をすると、この関数はconsCDRを、objectを参照するように変更します。この関数は値objectをreturnします。

以下はリストのCDRを、他のリストに置き換える例です。1番目の要素以外のすべての要素は、別のシーケンスまたは要素のために取り除かれます。1番目の要素はリストのCARなので変更されず、CDRを通じて到達することもできないからです。

(setq x '(1 2 3))
     ⇒ (1 2 3)
(setcdr x '(4))
     ⇒ (4)
x
     ⇒ (1 4)

リスト内のコンスセルのCDRを変更することにより、リストの途中から要素を削除できます。たとえば以下では、1番目のコンスセルのCDRを変更することにより、2番目の要素bを、リスト(a b c)から削除します。

(setq x1 '(a b c))
     ⇒ (a b c)
(setcdr x1 (cdr (cdr x1)))
     ⇒ (c)
x1
     ⇒ (a c)

以下に結果をボックス表記で示します:

                   --------------------
                  |                    |
 --------------   |   --------------   |    --------------
| car   | cdr  |  |  | car   | cdr  |   -->| car   | cdr  |
|   a   |   o-----   |   b   |   o-------->|   c   |  nil |
|       |      |     |       |      |      |       |      |
 --------------       --------------        --------------

以前は要素bを保持していた2番目のコンスセルは、依然として存在して、そのCARbのままですが、すでにこのリストの一部を形成していません。

CDRを変更して、新しい要素を挿入するのも、同じくらい簡単です:

(setq x1 '(a b c))
     ⇒ (a b c)
(setcdr x1 (cons 'd (cdr x1)))
     ⇒ (d b c)
x1
     ⇒ (a d b c)

以下に結果をボックス表記で示します:

 --------------        -------------       -------------
| car  | cdr   |      | car  | cdr  |     | car  | cdr  |
|   a  |   o   |   -->|   b  |   o------->|   c  |  nil |
|      |   |   |  |   |      |      |     |      |      |
 --------- | --   |    -------------       -------------
           |      |
     -----         --------
    |                      |
    |    ---------------   |
    |   | car   | cdr   |  |
     -->|   d   |   o------
        |       |       |
         ---------------

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.6.3 Functions that Rearrange Lists

以下では、リストの構成要素であるコンスセルのCDRを変更することにより、リストを“破壊的”に再配置する関数をいくつか示します。これらの関数が“破壊的”だという理由は、これらの関数が引数として渡された元のリストを処理して、return値となる新しいリストを形成するために、リストのコンスセルを再リンクするからです。

コンスセルを変更する他の関数については、Using Lists as Setsdelqを参照してください。

Function: nconc &rest lists

この関数は、listsの要素すべてを含むリストをreturnします。append (Building Cons Cells and Listsを参照してください)とは異なり、listsはコピーされません。かわりにlistsの各リストの最後のCDRが、次のリストを参照するように変更されます。listsの最後のリストは、変更されません。たとえば:

(setq x '(1 2 3))
     ⇒ (1 2 3)
(nconc x '(4 5))
     ⇒ (1 2 3 4 5)
x
     ⇒ (1 2 3 4 5)

nconcの最後の引数は変更されないので、上記の例のように、'(4 5)のような定数リストを使用するのが理に適っています。また、同じ理由により、最後の引数がリスとである必要はありません。

(setq x '(1 2 3))
     ⇒ (1 2 3)
(nconc x 'z)
     ⇒ (1 2 3 . z)
x
     ⇒ (1 2 3 . z)

しかし、(最後を除くすべての)他の引数はリストでなければなりません。

一般的な落とし穴としては、nconcにたいしてクォートされたリスト定数を、最後以外の引数として使用したときです。これを行なう場合、実行するごとにプログラムはリスト定数を変更するでしょう! 何が起こるのかを以下に示します:

(defun add-foo (x)            ; この関数ではfoo
  (nconc '(foo) x))           ;   を引数の前に追加させたい。

(symbol-function 'add-foo)
     ⇒ (lambda (x) (nconc (quote (foo)) x))

(setq xx (add-foo '(1 2)))    ; 動いているように見える。
     ⇒ (foo 1 2)
(setq xy (add-foo '(3 4)))    ; 何が起きているのか?
     ⇒ (foo 1 2 3 4)
(eq xx xy)
     ⇒ t

(symbol-function 'add-foo)
     ⇒ (lambda (x) (nconc (quote (foo 1 2 3 4) x)))
Function: nreverse list

この関数は、listの要素の順番を逆転します。reverseとは異なり、nreverseはリストを形成するCDR内のコンスセルを逆転することにより、引数を変更します。listの最後に使用されているコンスセルは、最初のコンスセルになります。

たとえば:

(setq x '(a b c))
     ⇒ (a b c)
x
     ⇒ (a b c)
(nreverse x)
     ⇒ (c b a)
;; 最初のコンスセルが最後になった。
x
     ⇒ (a)

わたしたちは通常、混乱を避けるために、nreverseの結果を、元のリストを保持していたのと同じ変数に格納します:

(setq x (nreverse x))

以下は、(a b c)を視覚的に表した、nreverseの例です:

元のリストの先頭:                         逆転されたリスト:
 -------------        -------------        ------------
| car  | cdr  |      | car  | cdr  |      | car | cdr  |
|   a  |  nil |<--   |   b  |   o  |<--   |   c |   o  |
|      |      |   |  |      |   |  |   |  |     |   |  |
 -------------    |   --------- | -    |   -------- | -
                  |             |      |            |
                   -------------        ------------
Function: sort list predicate

この関数は、listを安定的(しかし破壊的)にソートして、ソートされたリストをreturnします。この関数はpredicateを使用して要素を比較します。安定ソート(stable sort)では、同じソートキーをもつ要素が、ソートの前後で相対的に同じ順序が維持されます。安定性は、異なる条件によりソートするために要素を並び替えるために、連続したソートが使用されるときに重要です。

引数predicateは、2つの引数をとる関数でなければなりません。この関数はlistの2つの要素を引数として呼び出されます。昇順のソートを得るためのpredicateは、1番目の引数が、2番目の引数より“小さい”ときは非nil、それ以外はnilをreturnするようにします。

比較関数predicateは、少なくとも単独のsort呼び出しにおいて、任意の与えられた引数にたいして信頼できる結果を与えなければありません。比較関数は非対称的(antisymmetric) — つまりabより小さいとき、baより小さくない — でなければなりません。比較関数は推移的(transitive) — つまりabより小さく、bcより小さい場合、caより小さい — でなければなりません。これらの要求を満たさない比較関数を使用した場合、sortの結果は予測できません。

sortの破壊的な側面は、CDRを変更することにより、listを形成するコンスセルを再配置することです。非破壊的なソート関数の場合は、ソートされた要素を格納するために、あたらしいコンスセルを作成します。元のリストを破壊せずにソートされたコピーを作成したい場合は、copy-sequenceで最初にコピーしてから、それをソートします。

ソートはlist内のコンスセルのCARは変更しません。list内でCARに要素aを保持していたコンスセル、ソート後にもaを保持しますが、CDRは変更されるので、ソート後の位置は異なります。たとえば:

(setq nums '(1 3 2 6 5 4 0))
     ⇒ (1 3 2 6 5 4 0)
(sort nums '<)
     ⇒ (0 1 2 3 4 5 6)
nums
     ⇒ (1 2 3 4 5 6)

警告: numsのリストには0が含まれていないことに注意してください。これは前と同じコンスセルですが、リストの1番目ではなくなります。引数を保持するように形成された変数が、ソートされたリストでも保持されると仮定しないでください! かわりにsortの結果を保存して、それを使用してください。元のリストを保持していた変数に、結果を書き戻すことはよく行なわれます。

(setq nums (sort nums '<))

ソート処理を行なう他の関数については、Sorting Textを参照してください。sortの有用な例は、Access to Documentation Stringsdocumentationを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7 Using Lists as Sets

リストは順序なしの数学的集合 — リスト内に要素があれば集合の要素の値とされ、リスト内の順序は無視される — を表すことができます。2つの集合を結合(union)するには、(重複する要素を気にしない場合は)appendを使用します。equalである重複を取り除くには、delete-dupsを使用します。集合にたいする他の有用な関数には、memqdelq、およびこれらのequalバージョンであるmemberdeleteが含まれます。

Common Lispに関する注意: 集合を処理するために、Common Lispには(要素の重複がない)関数unionがあります。これらの関数は標準のGNU Emacs Lispにはありませんが、cl-libはこれらを提供します。Lists as Sets in Common Lisp Extensionsを参照してください。

Function: memq object list

この関数は、objectlistのメンバーかどうかをテストします。メンバーの場合、memqobjectで最初に見つかった要素から開始されるリストをreturnします。メンバーでない場合は、nilをreturnします。memqの文字‘q’は、この関数がobjectとリスト内の要素の比較に、eqを使用することを示します。たとえば:

(memq 'b '(a b c b a))
     ⇒ (b c b a)
(memq '(2) '((1) (2)))    ; (2)(2)eqではない。
     ⇒ nil
Function: delq object list

この関数listからはobjecteqなすべての要素を破壊的に取り除いて、結果のリストをreturnします。delqの文字‘q’は、この関数がobjectとリスト内の要素の比較に、eqを使用することを示します(memqremqと同様)。

delqを呼び出すときは通常、元のリストを保持していた変数にreturn値を割り当てて使用する必要があります(理由は以下参照)。

delq関数がリストの銭湯にある要素を削除する場合は、単にリストを読み進めて、この要素の後から開始される部分リストをreturnします。つまり:

(delq 'a '(a b c)) ≡ (cdr '(a b c))

リストの途中にある要素を削除するときは、必要なCDR(Altering the CDR of a Listを参照してください)を変更することにより削除します。

(setq sample-list '(a b c (4)))
     ⇒ (a b c (4))
(delq 'a sample-list)
     ⇒ (b c (4))
sample-list
     ⇒ (a b c (4))
(delq 'c sample-list)
     ⇒ (a b (4))
sample-list
     ⇒ (a b (4))

(delq 'a sample-list)は何も取り除きませんが(これは単に短いリストをreturnします)、(delq 'c sample-list)は3番目の要素を取り除いて、sample-listを変更することに注意してください。引数listを保持するように形成された変数が、実行後にもっと少ない要素になる、または元のリストを保持すると仮定しないでください! かわりにdelqの結果を保存して、それを使用してください。元のリストを保持していた変数に、結果を書き戻すことはよく行なわれます。

(setq flowers (delq 'rose flowers))

以下の例では、delqが比較しようとしている(4)と、sample-list内の(4)は、eqではありません:

(delq '(4) sample-list)
     ⇒ (a c (4))

与えられた値とequalな要素を削除したい場合は、delete(以下参照)を使用してください。

Function: remq object list

この関数は、objecteqなすべての要素が除かれた、listのコピーをreturnします。remqの文字‘q’は、この関数がobjectとリスト内の要素の比較に、eqを使用することを示します。

(setq sample-list '(a b c a b c))
     ⇒ (a b c a b c)
(remq 'a sample-list)
     ⇒ (b c b c)
sample-list
     ⇒ (a b c a b c)
Function: memql object list

関数memqlは、eql(浮動少数の要素は値で比較される)を使用してメンバーとeqlを比較することにより、objectlistのメンバーかどうかをテストします。objectがメンバーの場合、memqllist内で最初に見つかった要素から開始されるリストをreturnします。それ以外はnilをreturnします。

これをmemqと比較してみましょう:

(memql 1.2 '(1.1 1.2 1.3))  ; 1.21.2eql
     ⇒ (1.2 1.3)
(memq 1.2 '(1.1 1.2 1.3))  ; 1.21.2eqではない。
     ⇒ nil

以下の3つの関数はmemqdelqremqと似ていますが、要素の比較にeqではなく、equalを使用します。Equality Predicatesを参照してください。

Function: member object list

関数memberは、メンバーとobjectequalを使用して比較して、objectlistのメンバーかどうかをテストします。objectがメンバーの場合、memberlistで最初に見つかったところから開始されるリストをreturnします。それ以外はnilを参照してください。

これをmemqと比較してみましょう:

(member '(2) '((1) (2)))  ; (2) and (2) are equal.
     ⇒ ((2))
(memq '(2) '((1) (2)))    ; (2)(2)eqではない。
     ⇒ nil
;; 同じ内容の2つの文字列はequal
(member "foo" '("foo" "bar"))
     ⇒ ("foo" "bar")
Function: delete object sequence

この関数は、sequenceからobjectequalな要素を取り除いて、結果のシーケンスをreturnします。

sequenceがリストの場合、deletedelqに対応するように、membermemqに対応します。つまり、この関数はmemberと同様、要素とobjectの比較にequalを使用します。マッチする要素が見つかったら、delqが行なうように、その要素を取り除きます。delqと同様、通常は元のリストを保持していた変数にreturn値を割り当てて使用します。

sequenceがベクターまたは文字列の場合、deleteobjectequalなすべての要素を取り除いた、sequenceのコピーをreturnします。

たとえば:

(setq l '((2) (1) (2)))
(delete '(2) l)
     ⇒ ((1))
l
     ⇒ ((2) (1))
;; lの変更に信頼性を要するときは
;; (setq l (delete '(2) l))と記述する。
(setq l '((2) (1) (2)))
(delete '(1) l)
     ⇒ ((2) (2))
l
     ⇒ ((2) (2))
;; このケースではlのセットの有無に違いはない
;; しかし他のケースに倣ってセットするべき。
(delete '(2) [(2) (1) (2)])
     ⇒ [(1)]
Function: remove object sequence

この関数は、deleteに対応する非破壊的な関数です。この関数は、objectequalな要素を取り除いた、sequence(リスト、ベクター、文字列)のコピーをreturnします。たとえば:

(remove '(2) '((2) (1) (2)))
     ⇒ ((1))
(remove '(2) [(2) (1) (2)])
     ⇒ [(1)]

Common Lispに関する注意: GNU Emacs Lispの関数memberdeleteremoveは、Common Lispではなく、Maclispを継承しています。Common Lispでは、比較にequalを使用しません。

Function: member-ignore-case object list

この関数は、memberと同様ですが、objectが文字列で、大文字小文字とテキスト表現の違いを無視します。文字の大文字と小文字は等しいものとして扱われ、比較に先立ちユニバイト文字列はマルチバイト文字列に変換されます。

Function: delete-dups list

この関数は、listからすべてのequalな重複を、破壊的に取り除いて。、結果をlistに保管して、それをreturnします。list内の要素にequalな要素がいくつかある場合、delete-dupsは最初の要素を残します。

変数に格納されたリストに要素を追加したり、それを集合として使用する方法については、Modifying List Variablesの関数add-to-listも参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.8 Association Lists

連想配列(association list。短くはalist)は、キーと値のマッピングを記録します。これは連想(associations)と呼ばれるコンスセルのリストです。各コンスセルにおいて、CARキー(key)で、CDR連想値(associated value)になります。3

以下はalistの例です。キーpineは、値conesに関連付けられます。キーoakは、acornsに関連付けられます。キーmapleは、seedsに関連付けられます。

((pine . cones)
 (oak . acorns)
 (maple . seeds))

alist内の値とキーには、任意のLispオブジェクトを指定できます。たとえば以下のalist0では、シンボルaは数字1に、文字列"b"リスト(2 3)(alist要素のCDR)に関連付けられます。

((a . 1) ("b" 2 3))

要素のCDRCARに連想値を格納するようにalistデザインするほうがよい場合があります。以下は、そのようなalistです。

((rose red) (lily white) (buttercup yellow))

この例では、redroseに関連付けられる値だと考えます。この種のalistの利点は、CDRCDRの中に、他の関連する情報 — 他のアイテムのリストでさえ — を格納することができることです。不利な点は、与えられた値を含む要素を見つけるためにrassq(以下参照)を使用できないことです。これらを検討することが重要でない場合には、任意の与えられたalistにたいして一貫している限り、選択は好みの問題といえます。

上記で示したのと同じalistは、要素のCDRに連想値をもつと考えることができます。この場合、roseに関連付けられる値は、リスト(red)になるでしょう。

連想リストは、新しい連想を簡単にリストの先頭に追加できるので、スタックに保持したいような情報を記録するのによく使用されます。連想リストから与えられたキーにたいする連想を検索する場合、それが複数ある場合は、最初に見つかったものがreturnされます。

Emacs Lispでは、連想リストがコンスセルではない場合、それはエラーではありません。alist検索関数は、単にそのような要素を無視します。多くの他のバージョンのLいspでは、このような場合はエラーをシグナルします。

いくつかの観点において、プロパティーリストは連想リストと似ていることに注意してください。それぞれのキーが1度だけ出現するような場合、プロパティーリストは連想リストと同様に振る舞います。プロパティーリストと連想リストの比較については、Property Listsを参照してください。

Function: assoc key alist

この関数は、alist要素にたいしてkeyを比較するのにequalを使用して、alist内からkeyをもつ最初の連想をreturnします。CARkeyequalの連想がalistにない場合、この関数はnilをreturnします。たとえば:

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     ⇒ ((pine . cones) (oak . acorns) (maple . seeds))
(assoc 'oak trees)
     ⇒ (oak . acorns)
(cdr (assoc 'oak trees))
     ⇒ acorns
(assoc 'birch trees)
     ⇒ nil

以下はキーと値がシンボルでない場合の例です:

(setq needles-per-cluster
      '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(cdr (assoc 3 needles-per-cluster))
     ⇒ ("Pitch Pine")
(cdr (assoc 2 needles-per-cluster))
     ⇒ ("Austrian Pine" "Red Pine")

関数assoc-stringassocと似ていますが、文字列間の特定の違いを無視する点が異なります。Comparison of Characters and Stringsを参照してください。

Function: rassoc value alist

この関数は、alistの中から、値valueをもつ最初の連想をreturnします。CDRvalueequalの連想がalistにない場合、この関数はnilをreturnします。

rassocassocと似ていますが、CARではなく、alistの連想のCDRを比較します。この関数を、与えられた値に対応するキーを探す、“reverse assoc”と考えることができます。

Function: assq key alist

この関数は、alistからkeyをもつ最初の連想をreturnする点はassocと同様ですが、比較にequalではなくeqを使用します。CARkeyeqな連想がalist内に存在しない場合、assqnilをreturnします。eqequalより早く、ほとんどのalistはキーにシンボルを使用するので、この関数はassocより多用されます。Equality Predicatesを参照してください。

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     ⇒ ((pine . cones) (oak . acorns) (maple . seeds))
(assq 'pine trees)
     ⇒ (pine . cones)

反対に、キーがシンボルではないalistでは通常、assqは有用ではありません:

(setq leaves
      '(("simple leaves" . oak)
        ("compound leaves" . horsechestnut)))

(assq "simple leaves" leaves)
     ⇒ nil
(assoc "simple leaves" leaves)
     ⇒ ("simple leaves" . oak)
Function: rassq value alist

この関数は、alist内から値valueをもつ最初の連想をreturnします。alist内にCDRvalueeqな連想が存在しない場合は、nilをreturnします。

rassqassqと似ていますが、CARではなく、alistの各連想のCDRを比較します。この関数を、与えられた値に対応するキーを探す、“reverse assq”と考えることができます。

たとえば:

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(rassq 'acorns trees)
     ⇒ (oak . acorns)
(rassq 'spores trees)
     ⇒ nil

rassqは、要素のCDRCARに保管された値の検索はできません:

(setq colors '((rose red) (lily white) (buttercup yellow)))

(rassq 'white colors)
     ⇒ nil

この場合、連想(lily white)CDRwhiteではなく、リスト(white)です。これは連想をドットペア表記で記述すると明確になります:

(lily white) ≡ (lily . (white))
Function: assoc-default key alist &optional test default

この関数は、keyにたいするマッチをalistから検索します。alistの各要素にたいして、この関数は、keyと要素(アトムの場合)、または要素のCAR(コンスの場合)を比較します。比較はtestに2つの引数 — 要素(または要素のCAR)とkey — を与えて呼び出すことにより行なわれます。引数はこの順番で渡されるので、正規表現(Regular Expression Searchingを参照してください)を含むalistでは、string-matchを使用することにより有益な結果を得ることができます。testが省略されているかnilの場合は、比較にequalが使用されます。

alistの要素がこの条件によりkeyとマッチした場合、assoc-defaultはこの要素の値をreturnします。要素がコンスの場合、値は要素のCDRです。それ以外の場合、return値はdefaultです。

keyにマッチする要素がalistに存在しない場合、assoc-defaultnilをreturnします。

Function: copy-alist alist

この関数は、深さ2がレベルのalistのコピーをreturnします。この関数は各連想の新しいコピーを作成するので、元のalistを変更せずに、新しいalistを変更できます。

(setq needles-per-cluster
      '((2 . ("Austrian Pine" "Red Pine"))
        (3 . ("Pitch Pine"))
        (5 . ("White Pine"))))
⇒
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(setq copy (copy-alist needles-per-cluster))
⇒
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(eq needles-per-cluster copy)
     ⇒ nil
(equal needles-per-cluster copy)
     ⇒ t
(eq (car needles-per-cluster) (car copy))
     ⇒ nil
(cdr (car (cdr needles-per-cluster)))
     ⇒ ("Pitch Pine")
(eq (cdr (car (cdr needles-per-cluster)))
    (cdr (car (cdr copy))))
     ⇒ t

以下の例は、どのようにしてcopy-alistが他に影響を与えずにコピーの連想を変更可能なのかを示します:

(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
(cdr (assq 3 needles-per-cluster))
     ⇒ ("Pitch Pine")
Function: assq-delete-all key alist

この関数は、alistから、(delqを使用した場合は、そのような要素を1つずつ削除するのにたいして)CARkeyeqな要素すべてを削除します。この関数は短くなったalistをreturnし、alistの元のリスト構造を変更することもよくあります。正しい結果を得るために、alistに保存された値ではなく、assq-delete-allのreturn値を使用してください。

(setq alist '((foo 1) (bar 2) (foo 3) (lose 4)))
     ⇒ ((foo 1) (bar 2) (foo 3) (lose 4))
(assq-delete-all 'foo alist)
     ⇒ ((bar 2) (lose 4))
alist
     ⇒ ((foo 1) (bar 2) (lose 4))
Function: rassq-delete-all value alist

この関数は、alistからCDRvalueeqなすべての要素を削除します。この関数は短くなったリストをreturnし、alistの元のリスト構造を変更することもよくあります。rassq-delete-allassq-delete-allと似ていますが、CARではなくalistの各連想のCDRを比較します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.9 Property Lists

プロパティーリスト(property list。短くはplist)は、ペアになった要素のリストです。各ペアはプロパティー名(通常はシンボル)とプロパティー値を対応づけます。以下はプロパティーリストの例です:

(pine cones numbers (1 2 3) color "blue")

このプロパティーリストは、pineconesnumbers(1 2 3)color"blue"に関連づけます。プロパティー名とプロパティー値には任意のLispオブジェクトを指定できますが、通常プロパティー名は(この例のように)シンボルです。

いくつかのコンテキストでプロパティーリストが使用されます。たとえば、関数put-text-propertyはプロパティーリストを引数にとり、文字列またはバッファー内のテキストにたいして、テキストプロパティーと、テキストに適用するプロパティー値を指定します。Text Propertiesを参照してください。

プロパティーリストが頻繁に使用される他の例は、シンボルプロパティーの保管です。すべてのシンボルは、シンボルに関する様々な情報を記録するために、プロパティーのリストを処理します。これらのプロパティーはプロパティーリストの形式で保管されます。Symbol Propertiesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.9.1 Property Lists and Association Lists

連想リスト(Association Listsを参照してください)は、プロパティーリストとよく似ています。連想リストとは対照的に、プロパティー名は一意でなければならないので、プロパティーリスト内でペアの順序に意味はありません。

様々なLisp関数や変数に情報を付加するためには、連想リストよりプロパティーリストの方が適しています。プログラムでこのような情報すべてを1つの連想リストに保持する場合、特定のLisp関数や変数にたいする連想をチェックする度に、リスト全体を検索する必要が生じ、それにより遅くなる可能性があります。対照的に、関数名や変数自体のプロパティーリストに同じ情報を保持すれば、検索ごとにそのプロパティーリストの長さだけを検索するようになり、通常はこちらの方が短い時間で済みます。変数のドキュメントがvariable-documentationという名前のプロパティーに記録されているのは、これが理由です。同様にバイトコンパイラーも、特別に扱う必要がある関数を記録するためにプロパティーを使用します。

連想リストにも独自の利点があります。アプリケーションに依存しますが、プロパティーを更新するより、連想リストの先頭に連想を追加する方が速いでしょう。シンボルにたいするすべてのプロパティーは同じプロパティーリストに保管されるので、プロパティー名を異なる用途のために使用すると衝突の可能性があります(この理由により、そのプログラムで通常の変数や関数の名前につけるプレフィクスをプロパティー名の先頭につけることにより、一意と思われるプロパティー名を選ぶのはよいアイデアです)。連想リストは、連想をリストの先頭にpushし、後にある連想は無視されるので、スタックと同様に使用できます。これはプロパティーリストでは不可能です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.9.2 Property Lists Outside Symbols

以下の関数はプロパティーリストを操作するために使用されます。これらの関数はすべて、プロパティー名の比較にeqを使用します。

Function: plist-get plist property

この関数は、プロパティーリストplistに保管された、プロパティーpropertyの値をreturnします。この関数には、変形された(malformed)plist引数を指定できます。plistpropertyが見つからなかった場合、この関数はnilをreturnします。たとえば、

(plist-get '(foo 4) 'foo)
     ⇒ 4
(plist-get '(foo 4 bad) 'foo)
     ⇒ 4
(plist-get '(foo 4 bad) 'bad)
     ⇒ nil
(plist-get '(foo 4 bad) 'bar)
     ⇒ nil
Function: plist-put plist property value

この関数は、プロパティーリストplistに、プロパティーpropertyの値として、valueを保管します。この関数はplistを破壊的に変更するかもしれず、元のリスト構造を変更せずに新しいリストを構築することもあります。この関数は変更されたプロパティーリストをreturnするので、plistを取得した場所に書き戻すことができます。たとえば、

(setq my-plist '(bar t foo 4))
     ⇒ (bar t foo 4)
(setq my-plist (plist-put my-plist 'foo 69))
     ⇒ (bar t foo 69)
(setq my-plist (plist-put my-plist 'quux '(a)))
     ⇒ (bar t foo 69 quux (a))
Function: lax-plist-get plist property

plist-getと同様ですが、プロパティーの比較にeqではなくequalを使用します。

Function: lax-plist-put plist property value

plist-putと同様ですが、プロパティーの比較にeqではなくequalを使用します。

Function: plist-member plist property

この関数は与えられたpropertyplistに含まれる場合は、非nilをreturnします。plist-getとは異なり、この関数は存在しないプロパティーと、値がnilのプロパティーを区別できます。実際にreturnされる値は、carpropertyで始まる、plistの後尾部分です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6 Sequences, Arrays, and Vectors

シーケンス(sequence)型は、2つの異なるLisp型 — リストと配列 — を結合した型です。他の言い方をすると、任意のリストはシーケンスであり、任意の配列はシーケンスです。すべてのシーケンスがもつ共通な属性は、それぞれが順序づけされた要素のコレクションであることです。

配列(array)は各スロットが要素である、固定長のオブジェクトです。すべての要素に一定時間でアクセスできます。配列の4つの型として、文字列、ベクター、文字テーブル、ブールベクターがあります。

リストは要素のシーケンスですが、要素は単一の基本オブジェクトではありません。リストはコンスセルにより作られ、要素ごとに1つのセルをもちます。n番目の要素を探すには、n個のコンスセルを走査する必要があるので、先頭から離れた要素ほどアクセスに時間を要します。しかしリストは要素の追加や削除が可能です。

以下の図は、これらの型の関連を表します:

          _____________________________________________
         |                                             |
         |          Sequence                           |
         |  ______   ________________________________  |
         | |      | |                                | |
         | | List | |             Array              | |
         | |      | |    ________       ________     | |
         | |______| |   |        |     |        |    | |
         |          |   | Vector |     | String |    | |
         |          |   |________|     |________|    | |
         |          |  ____________   _____________  | |
         |          | |            | |             | | |
         |          | | Char-table | | Bool-vector | | |
         |          | |____________| |_____________| | |
         |          |________________________________| |
         |_____________________________________________|

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 Sequences

このセクションでは、任意の種類のシーケンスを許す関数を説明します。

Function: sequencep object

この関数は、objectがリスト、ベクター、文字列、ブールベクター、文字テーブルの場合はt、それ以外はnilをreturnします。

Function: length sequence

この関数は、sequence内の要素の数をreturnします。sequenceがドットリストの場合、wrong-type-argumentエラーがシグナルされます。循環リストは無限ループを引き起こします。文字テーブルでは、Emacsの最大文字コードより、常に1大きい値がreturnされます。

関連する関数safe-lengthについては、Definition of safe-lengthを参照してください。

(length '(1 2 3))
    ⇒ 3
(length ())
    ⇒ 0
(length "foobar")
    ⇒ 6
(length [1 2 3])
    ⇒ 3
(length (make-bool-vector 5 nil))
    ⇒ 5

Text Representationsstring-bytesも参照してください。

ディスプレー上での文字列の幅を計算する必要がある場合、文字数だけを数えて各文字のディスプレー幅を計算しないlengthではなく、string-width (Size of Displayed Textを参照してください)を使用するべきです。

Function: elt sequence index

この関数は、indexによりインデックスづけされた、sequenceの要素をreturnします。indexの値として妥当なのは、0からsequenceの長さより1小さい数までの範囲の整数です。sequenceがリストの場合、範囲外の値はnthと同じように振る舞います。Definition of nthを参照してください。それ以外の場合、範囲外の値はargs-out-of-rangeエラーを引き起こします。

(elt [1 2 3 4] 2)
     ⇒ 3
(elt '(1 2 3 4) 2)
     ⇒ 3
;; eltがどの文字をreturnするか明確にするためにstringを使用。
(string (elt "1234" 2))
     ⇒ "3"
(elt [1 2 3 4] 4)
     error→ Args out of range: [1 2 3 4], 4
(elt [1 2 3 4] -1)
     error→ Args out of range: [1 2 3 4], -1

この関数は、aref (Functions that Operate on Arraysい)とnth (Definition of nthを参照してください)を一般化したものです。

Function: copy-sequence sequence

この関数は、sequenceのコピーをreturnします。コピーは元のシーケンスと同じ型で、同じ要素が同じ順番でもちます。

コピーに新しい要素を格納するのは、元のsequenceに影響を与えず、その逆も真です。しかし新しいシーケンス内の要素がコピーされたものでない場合は、元のシーケンスの要素と同一(eq)になります。したがって、コピーされたシーケンスを通じて見つかった要素を変更すると、この変更は元のシーケンスでも見ることができます。

シーケンスがテキストプロパティーをともなう文字列の場合、コピー内のプロパティーリスト自身もコピーとなり、元のシーケンスのプロパティーリストと共有はされません。しかし、プロパティーリストの実際の値は共有されます。Text Propertiesを参照してください。

この関数は、ドットリストでは機能しません。循環リストのコピーは、無限ループを起こすでしょう。

シーケンスをコピーする別の方法は、Building Cons Cells and ListsappendCreating StringsconcatFunctions for Vectorsvconcatも参照してください。

(setq bar '(1 2))
     ⇒ (1 2)
(setq x (vector 'foo bar))
     ⇒ [foo (1 2)]
(setq y (copy-sequence x))
     ⇒ [foo (1 2)]

(eq x y)
     ⇒ nil
(equal x y)
     ⇒ t
(eq (elt x 1) (elt y 1))
     ⇒ t

;; 一方のシーケンスの要素を置き換え。
(aset x 0 'quux)
x ⇒ [quux (1 2)]
y ⇒ [foo (1 2)]

;; 共有された要素の内部を変更。
(setcar (aref x 1) 69)
x ⇒ [quux (69 2)]
y ⇒ [foo (69 2)]

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 Arrays

配列(array)オブジェクトは、いくつかのLispオブジェクトを保持するスロットをもち、これらのオブジェクトは配列の要素と呼ばれます。配列内の任意の要素は、一定時間でアクセスされます。対照的に、リスト内の要素のアクセスに要する時間は、その要素がリスト内のどの位置にあるかに比例します。

Emacsは4つの配列型 —文字列(strings。String Typeを参照してください)ベクター(vectors。Vector Typeを参照してください)ブールベクター(bool-vectors。Bool-Vector Typeを参照してください)文字テーブル(char-tables。Char-Table Typeを参照してください) — を定義し、これらはすべて1次元です。ベクターと文字テーブルは任意の型の要素を保持できますが、文字列は文字だけ、ブールベクターはtnilしか保持できません。

4種のすべての配列は、これらの特性を共有します:

配列を作成したとき、文字テーブル以外では、長さを指定しなければなりません。文字テーブルの長さは、文字コードの範囲により決定されるので、長さを指定できません。

原則として、テキスト文字の配列が欲しい場合は、文字列とベクターのどちらかを使用できます。実際のところ、そのような用途にたいしては、4つの理由により、わたしたちは常に文字列を選択します:

対照的に、(キーシーケンスのような)キーボード入力文字の配列では、多くのキーボード入力文字は、文字列に収まる範囲の外にあるので、ベクターが必要になるでしょう。Key Sequence Inputを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 Functions that Operate on Arrays

このセクションでは、すべての型の配列に適用される関数を説明します。

Function: arrayp object

この関数は、objectが配列(ベクター、文字列、ブールベクター、文字テーブル)の場合は、tをreturnします。

(arrayp [a])
     ⇒ t
(arrayp "asdf")
     ⇒ t
(arrayp (syntax-table))    ;; 文字テーブル。
     ⇒ t
Function: aref array index

この関数は、arrayindex番目の要素をreturnします。1番目の要素のインデクスは0です。

(setq primes [2 3 5 7 11 13])
     ⇒ [2 3 5 7 11 13]
(aref primes 4)
     ⇒ 11
(aref "abcdefg" 1)
     ⇒ 98           ; b’のASCIIコードは98。

Sequencesの関数eltも参照してください。

Function: aset array index object

この関数は、arrayindex番目の要素を、objectにセットします。この関数はobjectをeturnします。

(setq w [foo bar baz])
     ⇒ [foo bar baz]
(aset w 0 'fu)
     ⇒ fu
w
     ⇒ [fu bar baz]

(setq x "asdfasfd")
     ⇒ "asdfasfd"
(aset x 3 ?Z)
     ⇒ 90
x
     ⇒ "asdZasfd"

arrayが文字列でobjectが文字でない場合、結果はwrong-type-argumentエラーになります。この関数は、文字列の挿入で必要な場合は、ユニバイト文字列をマルチバイト文字列に変換します。

Function: fillarray array object

この関数は配列arrayobjectで充填するので、arrayのすべての要素はobjectになります。この関数はarrayをreturnします。

(setq a [a b c d e f g])
     ⇒ [a b c d e f g]
(fillarray a 0)
     ⇒ [0 0 0 0 0 0 0]
a
     ⇒ [0 0 0 0 0 0 0]
(setq s "When in the course")
     ⇒ "When in the course"
(fillarray s ?-)
     ⇒ "------------------"

arrayが文字列でobjectが文字でない場合、結果はwrong-type-argumentエラーになります。

配列と判っているオブジェクトにたいしては、一般的なシーケンス関数copy-sequenceおよびlengthが有用なときが多くあります。Sequencesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4 Vectors

ベクター(vector)とは、任意のLispオブジェクトを要素にもつことができる、一般用途のための配列です(対照的に、文字列の要素は文字だけですStrings and Charactersを参照してください)。Emacsではベクターは、キーシーケンス(Key Sequencesを参照してください)、シンボル検索用のテーブル(Creating and Interning Symbolsを参照してください)、バイトコンパイルされた関数表現の一部(Byte Compilationを参照してください)など、多くの目的で使用されます。

他の配列と同様、ベクターは0基準のインデックスづけを使用し、1番目の要素はインデックス0になります。

ベクターは、角カッコ(square brackets)で囲まれた要素としてプリントされます。したがって、シンボルabaを要素にもつベクターは、[a b a]とプリントされます。Lisp入力として、同じ方法でベクターを記述できます。

文字列や数値と同様に、ベクターは定数として評価され、評価された結果は同じベクターになります。ベクターの要素は評価も確認もされません。Self-Evaluating Formsを参照してください。

以下はこれらの原理を表す例です:

(setq avector [1 two '(three) "four" [five]])
     ⇒ [1 two (quote (three)) "four" [five]]
(eval avector)
     ⇒ [1 two (quote (three)) "four" [five]]
(eq avector (eval avector))
     ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5 Functions for Vectors

ベクターに関連した関数をいくつか示します:

Function: vectorp object

この関数は、objectがベクターの場合は、tをreturnします。

(vectorp [a])
     ⇒ t
(vectorp "asdf")
     ⇒ nil
Function: vector &rest objects

この関数は、引数objectsを要素にもつベクターを作成してreturnします。

(vector 'foo 23 [bar baz] "rats")
     ⇒ [foo 23 [bar baz] "rats"]
(vector)
     ⇒ []
Function: make-vector length object

この関数は、objectに初期化されたlength個の要素からなる、新しいベクターをreturnします。

(setq sleepy (make-vector 9 'Z))
     ⇒ [Z Z Z Z Z Z Z Z Z]
Function: vconcat &rest sequences

この関数は、sequencesのすべての要素を含む、新しいベクターをreturnします。引数sequencesは真リスト、ベクター、文字列、ブールベクターです。sequencesが与えられない場合、空のベクターがreturnされます。

値は空のベクター、または任意の既存のベクターとeqではない、新しい空ではないベクターのどちらかです。

(setq a (vconcat '(A B C) '(D E F)))
     ⇒ [A B C D E F]
(eq a (vconcat a))
     ⇒ nil
(vconcat)
     ⇒ []
(vconcat [A B C] "aa" '(foo (6 7)))
     ⇒ [A B C 97 97 foo (6 7)]

vconcat関数は、引数としてバイトコード関数オブジェクトもとることができます。これは、バイトコード関数オブジェクトの内容全体にアクセスするのを容易にするための、特別な機能です。Byte-Code Function Objectsを参照してください。

結合を行なう他の関数については、Mapping FunctionsmapconcatCreating StringsconcatBuilding Cons Cells and Listsappendを参照してください。

append関数は、ベクターを同じ要素をもつリストに変換する方法も提供します:

(setq avector [1 two (quote (three)) "four" [five]])
     ⇒ [1 two (quote (three)) "four" [five]]
(append avector nil)
     ⇒ (1 two (quote (three)) "four" [five])

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6 Char-Tables

文字テーブル(char-table)はベクターとよく似ていますが、文字テーブルは文字コードによりインデックスづけされます。文字テーブルのインデックスには、修飾キーをともなわない任意の有効な文字コードを使用できます。他の配列と同様に、arefasetで、文字テーブルの要素にアクセスできます。加えて、文字テーブルは、追加のデータを保持するために、特定の文字コードに関連づけられていない、エキストラスロット(extra slots)をもつことができます。ベクターと同様、文字テーブルは、定数として評価され、任意の型の要素を保持できます。

文字テーブルはそれぞれサブタイプ(subtype)をもち、これは2つの目的を担うシンボルです:

文字テーブルは親(parent)をもつことができ、これは他の文字テーブルです。文字テーブルが親をもつ場合、その文字テーブルで特定の文字cにたいしてnilが指定されているときは、親として指定された文字テーブルで指定された値を継承します。言い方を変えると、文字テーブルchar-tablecnilが指定されている場合、(aref char-table c)char-tableの親の値をreturnします。

文字テーブルはデフォルト値(default value)をもつこともできます。デフォルト値をもつとき、文字テーブルchar-tablecにたいしてnil値を指定すると、(aref char-table c)はデフォルト値をreturnします。

Function: make-char-table subtype &optional init

サブタイプsubtype(シンボル)をもつ、新たに作成された文字テーブルをreturnします。各要素はinitに初期化され、デフォルトはnilです。文字テーブルが作成された後で、文字テーブルのサブタイプを変更することはできません。

すべての文字テーブルは、インデックスとなる任意の有効な文字テーブルのための空間をもつので、文字テーブルの長さを指定する引数はありません。

subtypechar-table-extra-slotsシンボルプロパティーをもつ場合、それはその文字列テーブル内のエキストラスロットの数を指定します。値には0から10の整数を指定し、これ以外の場合make-char-tableはエラーとなります。subtypechar-table-extra-slotsシンボルプロパティー(Property Listsを参照してください)をもたない場合、その文字テーブルはエキストラスロットをもちません。

Function: char-table-p object

この関数は、objectが文字テーブルの場合はt、それ以外はnilをreturnします。

Function: char-table-subtype char-table

この関数は、char-tableのサブタイプのシンボルをreturnします。

文字テーブルのデフォルト値にアクセスするための、特別な関数は存在しません。これを行なうには、char-table-rangeを使用します(以下参照)。

Function: char-table-parent char-table

この関数は、char-tableの親をreturnします。親は常に、nil、または他の文字テーブルです。

Function: set-char-table-parent char-table new-parent

この関数は、char-tableの親を、new-parentにセットします。

Function: char-table-extra-slot char-table n

このガン数は、char-tableのエキストラスロットnの内容をreturnします。文字テーブルのエキストラスロットの数は、文字テーブルのサブタイプにより決定されます。

Function: set-char-table-extra-slot char-table n value

この関数は、char-tableのエキストラスロットnに、valueを格納します。

文字テーブルは、1つの文字コードにたいして、1つの要素値(element value)を指定できます。文字テーブルは文字セット全体にたいして値を指定することもできます。

Function: char-table-range char-table range

この関数は、文字範囲rangeにたいして、char-tableで指定された値をreturnします。可能なrangeは以下のとおりです:

nil

デフォルト値への参照。

char

文字charにたいする要素への参照(charは有効な文字コードであると仮定)。

(from . to)

包括的な範囲‘[from..to]’内のすべての文字を参照するコンスセル。

Function: set-char-table-range char-table range value

この関数は、char-table内の文字範囲rangeにたいして値をセットします。可能なrangeは、以下のとおりです:

nil

デフォルト値への参照。

t

文字コード範囲の全体を参照。

char

文字charにたいする要素への参照(charは有効な文字コードであると仮定)。

(from . to)

包括的な範囲‘[from..to]’内のすべての文字を参照するコンスセル。

Function: map-char-table function char-table

この関数は、char-tableの非nil値ではない各要素にたいして、引数functionを呼び出します。functionの呼び出しでは、2つの引数(keyとvalue)が指定されます。keyはchar-table-rangeにたいする可能なrange — 有効な文字か、同じ値を共有する文字範囲を指定するコンスセル(from . to)です。valueは、(char-table-range char-table key)がreturnする値です。

全体的に見て、functionに渡されるkey-valueのペアは、char-tableに格納されたすべての値を表します。

return値はm常にnilです。map-char-table呼び出しを有用にするために、functionは副作用をもつべきです。たとえば、以下は構文テーブルを調べる方法です:

(let (accumulator)
   (map-char-table
    #'(lambda (key value)
        (setq accumulator
              (cons (list
                     (if (consp key)
                         (list (car key) (cdr key))
                       key)
                     value)
                    accumulator)))
    (syntax-table))
   accumulator)
⇒
(((2597602 4194303) (2)) ((2597523 2597601) (3))
 ... (65379 (5 . 65378)) (65378 (4 . 65379)) (65377 (1))
 ... (12 (0)) (11 (3)) (10 (12)) (9 (0)) ((0 8) (3)))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.7 Bool-vectors

ブールベクター(bool-vector)はベクターとよく似ていますが、値にtnilしか格納できません。ブールベクターの要素に非nil値の格納を試みた場合、そこにtが格納されます。すべての配列と同様、ブールベクターのインデックスは0から開始され、1度ブールベクターが作成されたら、長さを変更することはできません。ブールベクターは定数として評価されます。

ブールベクターを処理する、特別な関数が2つあります。その関数意外にも、他の種類の配列に使用されるのと同じ関数で、ブールベクターを操作できます。

Function: make-bool-vector length initial

initialに初期化された、length要素の新しいブールベクターをreturnします。

Function: bool-vector-p object

この関数は、objectがブールベクターであればt、それ以外はnilをreturnします。

以下で説明するように、ブールベクターのセット処理を行なう関数がいくつかあります:

Function: bool-vector-exclusive-or a b &optional c

ブールベクターabの、ビットごとの排他的論理和(bitwise exclusive or)をreturnします。オプション引数cが与えられた場合、この処理の結果はcに格納されます。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-union a b &optional c

ブールベクターabの、ビットごとの論理和(bitwise or)をreturnします。オプション引数cが与えられた場合、この処理の結果はcに格納されます。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-intersection a b &optional c

ブールベクターabの、ビットごとの論理積(bitwise and)をreturnします。オプション引数cが与えられた場合、この処理の結果はcに格納されます。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-set-difference a b &optional c

ブールベクターabの、差集合(set difference)をreturnします。オプション引数cが与えられた場合、この処理の結果はcに格納されます。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-not a &optional b

ブールベクターaの、補集合(set complement)をreturnします。オプション引数bが与えられた場合、この処理の結果はbに格納されます。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-subsetp a b

a内のすべてのt値が、bでもt値の場合はt、それ以外はnilをreturnします。引数はすべて、同じ長さのブールベクターを指定します。

Function: bool-vector-count-consecutive a b i

iから始まるaの、bと等しい連続する要素の数をreturnします。aはブールベクターで、btniliaのインデックスです。

Function: bool-vector-count-population a

ブールベクターaの、tの要素の数をreturnします。

以下はブールベクターを作成、確認、更新する例です。長さ8以下のブール値のプリント表記は、1つの文字で表されることに注意してください。

(setq bv (make-bool-vector 5 t))
     ⇒ #&5"^_"
(aref bv 1)
     ⇒ t
(aset bv 3 nil)
     ⇒ nil
bv
     ⇒ #&5"^W"

control-_の2進コードは11111、control-Wは10111なので、この結果は理解できるでしょう。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8 Managing a Fixed-Size Ring of Objects

リング(ring)は、挿入、削除、ローテーション、剰余(modulo)でインデックスづけされた参照と走査(traversal)をサポートする、固定長のデータ構造です。ringパッケージにより、効率的なリングデータ構造が実装されています。このパッケージは、このセクションにリストされた関数を提供します。

killリングやマークリングのような、Emacsにあるいくつかの“リング”は、実際には単なるリストとして実装されていることに注意してください。したがって、これらのリングにたいしては、以下の関数は機能しないでしょう。

Function: make-ring size

この関数は、sizeオブジェクトを保持できる、新しいリングをreturnします。sizeは整数です。

Function: ring-p object

この関数は、objectがリングの場合はt、それ以外はnilをreturnします。

Function: ring-size ring

この関数は、ringの最大の要素数をreturnします。

Function: ring-length ring

この関数は、ringに現在含まれている、オブジェクトの数をreturnします。値は、ring-sizeでreturnされる値を超えることはありません。

Function: ring-elements ring

この関数は、ring内のオブジェクトのリストをreturnします。リストの順序は、新しいオブジェクトが先頭になります。

Function: ring-copy ring

個の関数は、ringのコピーを新しいリングとしてreturnします。新しいリングは、ringと同じ(eqな)オブジェクトを含みます。

Function: ring-empty-p ring

この関数は、ringが空の場合はt、それ以外はnilをreturnします。

リング内の1番新しい要素は、常にインデックス0をもちます。より大きいインデックスは、より古い要素に対応します。インデックスは、リング長のmoduloにより計算されます。インデックス-1は1番古い要素、-2は次に古い要素、...となります。

Function: ring-ref ring index

この関数はインデックスindexにあるring内のオブジェクトをreturnします。indexには負、またはリング長より大きい数を指定できます。ringがからの場合、ring-refはエラーをシグナルします。

Function: ring-insert ring object

この関数は、1番新しい要素としてobjectringに挿入し、objectをreturnします。

リングが一杯の場合、新しい要素のための空きを作るため、挿入により1番古い要素が削除されます。

Function: ring-remove ring &optional index

ringからオブジェクトを削除して、そのオブジェクトをreturnします。引数indexは、どのアイテムを削除するかを指定します。これがnilの場合、それは1番古いアイテムを削除することを意味します。ringが空の場合、ring-removeはエラーをシグナルします。

Function: ring-insert-at-beginning ring object

この関数は、1番古い要素として、objectringに挿入します。return値は、意味をもちません。

リングが一杯の場合、この関数は挿入される要素のための空きを作るために、1番新しい要素を削除します。

リングサイズを超えることを気にしない場合、そのリングをFIFO(first-in-first-out: 先入れ先出し)のキューとして使用することができます。たとえば:

(let ((fifo (make-ring 5)))
  (mapc (lambda (obj) (ring-insert fifo obj))
        '(0 one "two"))
  (list (ring-remove fifo) t
        (ring-remove fifo) t
        (ring-remove fifo)))
     ⇒ (0 t one t "two")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7 Hash Tables

ハッシュテーブル(hash table)は、非常に高速なルックアップテーブルの一種で、キーを対応する値にマップするという点では、alist(Association Listsを参照してください)に似ています。ハッシュテーブルは、以下の点でalistと異なります:

Emacs Lispは、それらを処理する一連の関数とともに、一般的な用途のハッシュテーブルデータ型を提供します。ハッシュテーブルは特別なプリント表現をもち、それは‘#s’と、その後にハッシュテーブルのプロパティーと内容お指定するリストが続きます。Creating Hash Tablesを参照してください。(用語“ハッシュ表記(hash notation)”は、プリント表現の最初に‘#’を使用する、入力構文をもたないオブジェクトのことを指し、これは用語“ハッシュテーブル(hash table)”にたいしては使用されません。Printed Representation and Read Syntaxを参照してください。)

obarray(オブジェクト配列)もハッシュテーブルの一種ですが、これらは異なる型のオブジェクトで、intern(インターン)されたシンボルを記録するためだけに使用されます(Creating and Interning Symbolsを参照してください)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 Creating Hash Tables

ハッシュテーブルを作成する基本的な関数は、make-hash-tableです。

Function: make-hash-table &rest keyword-args

この関数は、指定された引数に対応する、新しいハッシュテーブルを作成します。引数は、キーワード(特別に認識される独自のシンボル)と、それに対応する値を交互に指定することにより構成されます。

make-hash-tableでは、いくつかのキーワードが意味をもちますが、実際に知る必要があるのは、:test:weaknessの2つだけです。

:test test

これは、このハッシュテーブルにたいしてキーを照合する方法を指定します。デフォルトはeqlであり、他の代替としてはeqequalがあります:

eql

キーが数字の場合、それらがequalであれば、つまり、それらの値が等しく、どちらも整数、あるいはどちらも浮動少数の場合は“同一”です。それ以外では、2つの別々のオブジェクトは、決して“同一”になりません。

eq

2つの個別のLispオブジェクトはすべて、“別”のキーです。

equal

2つの個別のLispオブジェクトにたいして、それらがequalの場合、“同一”のキーです。

testにたいして追加の選択肢を定義するために、define-hash-table-test (Defining Hash Comparisonsを参照してください)を使用することができます。

:weakness weak

ハッシュテーブルのweakness(強度)は、ハッシュテーブル内に存在するキーと値を、ガーベージコレクションから保護するかどうかを指定します。

weakは、nilkeyvaluekey-or-valuekey-and-value、またはt(key-and-valueのエイリアス)のうちの1つを指定しなければなりません。weakkeyの場合、そのハッシュテーブルは、(キーが他の場所で参照されていなければ)ハッシュテーブルのキーがガーベージコレクトされるのを妨げません。ある特定のキーがガーベージコレクトされた場合、それに対応する連想は、ハッシュテーブルから削除されます。

weakvalueの場合、そのハッシュテーブルは、(値が他の場所で参照されていなければ)ハッシュテーブルの値がガベージコレクトされるのを妨げません。あるP特定の値がガーベージコレクトされた場合、それに対応する連想は、ハッシュテーブルから削除されます。

weakkey-and-value(またはt)の場合、その連想を保護するために、キーと値の両方が生きていなければなりません。したがって、そのハッシュテーブルは、キーと値のどちらかをガーベージコレクトから守ることはしません。キーか値のどちらか一方がガーベージコレクトされたら、その連想は削除されます。

weakkey-or-valueの場合、キーか値のどちらか一方で、その連想を保護することができます。したがって、キーと値の両方がガベージコレクトされたときだけ(それがハッシュテーブル自体にたいする参照でなければ)、ハッシュテーブルからその連想が削除されます。

weakにたいするデフォルトはnilなので、ハッシュテーブルから参照されているキーと値のすべては、ガーベージコレクションから保護されます。

:size size

これは、そのハッシュテーブルに連想を保管しようと計画している、連想の数にたいするヒントを指定します。数が概算で判っている場合、この方法でそれを指定することにより、処理を少し効率的にすることができます。小さすぎるサイズを指定した場合、そのハッシュテーブルは必要に応じて自動的に拡張子マスが、これを行なうには時間が余計にかかります。

デフォルトのサイズは65です。

:rehash-size rehash-size

ハッシュテーブルに連想を追加するとき、そのテーブルが“一杯(full)”の場合、テーブルは自動的に拡張します。この値は、そのときどれだけハッシュテーブルを拡張するかを指定します。

rehash-sizeが整数の場合(それは正であるべきです)、通常のサイズにrehash-sizeを加えることにより、ハッシュテーブルが拡張されます。rehash-sizeが浮動小数の場合(1より大きい方がよい)は、古いサイズにその数を乗じることにより、ガッシュテーブルが拡張されます。

デフォルト値は1.5です。

:rehash-threshold threshold

これは、ハッシュテーブルが“一杯(full)”(なのでもっと大きく拡張する必要がある)だと判断される基準を指定します。thresholdの値は、1以下の、正の浮動小数点数であるべきです。実際のエントリー数が、通常のサイズにたいする指定した割合を超えた場合、そのハッシュテーブルは“一杯”になります。thresholdのデフォルトは、0.8です。

Function: makehash &optional test

この関数はmake-hash-tableと同じですが、異なるスタイルの引数リストを指定します。引数testは、キーを照合する方法を指定します。

この関数は時代遅れです。かわりにmake-hash-tableを使用してください。

ハッシュテーブルのプリント表現を使用して、新しいハッシュテーブルを作成することもできます。指定されたハッシュテーブル内の各要素が、有効な入力構文(Printed Representation and Read Syntaxを参照してください)をもっていれば、Lispリーダーをこのプリント表現を読み取ることができます。たとえば以下は、値val1(シンボル)と300(数字)に関連づけられた、キーkey1key2(両方ともシンボル)を、新しいハッシュテーブルを指定します。

#s(hash-table size 30 data (key1 val1 key2 300))

ハッシュテーブルのプリント表現は、‘#s’と、その後の‘hash-table’で始まるリストにより構成されます。このリストの残りの部分は、そのハッシュテーブルのプロパティーと初期内容を指定する、0個以上のプロパティーと値のペアで構成されるべきです。プロパティーと値は、そのまま読み取られます。有効なプロパティー名は、sizetestweaknessrehash-sizerehash-threshold、およびdataです。dataプロパティーは、初期ないようにたいするキーと値のペアのリストであるべきです。他のプロパティーは、上記で説明したmake-hash-tableのキーワード(:size:testなど)と同じ意味をもちます。

バッファーやフレームのような、入力構文をもたないオブジェクトを含む初期内容をもつハッシュテーブルを指定できないことに注意してください。そのようなオブジェクトは、ハッシュテーブルが作成された後に追加します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.2 Hash Table Access

このセクションでは、ハッシュテーブルにアクセスしたり、連想を保管する関数を説明します。一般的に、比較方法による制限がない限り、任意のLispオブジェクトをハッシュキーとして使用できます。

Function: gethash key table &optional default

この関数はtablekeyを照合して、それに関連づけられたvaluetable内にkeyをもつ連想が存在しない場合はdefault — をreturnします。

Function: puthash key value table

この関数は、table内に、値valueをもつkeyの連想を挿入します。tableがすでにkeyの連想をもつ場合、valueにより古い連想値が置き換えられます。

Function: remhash key table

この関数は、tablekeyの連想がある場合は、それを削除します。keyが連想をもたない場合、remhashは何も行ないません。

Common Lispに関する注意: Common Lispでは、remhashが実際に連想を削除したときは非nil、それ以外はnilをreturnします。Emacs Lispでは、remhashは常にnilをreturnします。

Function: clrhash table

この関数は、ハッシュテーブルtableからすべての連想を削除するので、そのハッシュテーブルは空になります。これはハッシュテーブルのクリーニング(clearing)とも呼ばれます。

Common Lispに関する注意: Common Lispでは、clrhashは空のtableをreturnします。Emacs Lispではnilをreturnします。

Function: maphash function table

この関数は、table内の各連想にたいして、1度ずつfunctionを呼び出します。関数functionは2つの引数 — tableにリストされたkeyと、それに関連づけられたvalue — をとるべきです。maphashnilをreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.3 Defining Hash Comparisons

define-hash-table-testにより、キーを照合する新しい方法を定義できます。この機能を使用するには、ハッシュテーブルの動作方法と、ハッシュコード(hash code)の意味を理解する必要があります。

概念的にはハッシュテーブルを、1つの連想を保持できるスロットがたくさんある巨大な配列として考えることができます。キーを照合するには、まずgethashが、キーから整数のハッシュコード(hash code)を計算します。配列内のインデックスを生成するために、gethashは、配列の長さにより、この整数のmoduloを得ます。それからキーが見つかったかどうか確認するために、そのスロット、もし必要なら近くのスロットを探します。

したがってキー照合の新しい方法を定義するためには、キーからハッシュコードを計算する関数と、2つのキーを直接比較する関数の両方が必要です。

Function: define-hash-table-test name test-fn hash-fn

この関数は、nameという名前の、新たなハッシュテーブルテストを定義します。

この方法でnameを定義した後では、make-hash-tableの引数testにこれを使用することができます。それを行なう場合、そのハッシュテーブルはキー値の比較にtest-fn、キー値から“ハッシュコード”を計算するためにhash-fnを使用することになります。

関数test-fnは2つの引数(2つのキー)をとり、それらが“同一”と判断されたときは非nilをreturnします。

関数hash-fnは1つの引数(キー)をとり、そのキーの“ハッシュコード”(整数)をreturnします。よい結果を得るために、この関数は負の整数を含む整数の全範囲を、ハッシュコードに使用するべきです。

指定された関数は、プロパティーhash-table-testの配下の、nameというプロパティーリストに格納されます。そのプロパティーの値形式は、(test-fn hash-fn)です。

Function: sxhash obj

この関数は、Lispオブジェクトobjにたいするハッシュコードをreturnします。return値は、objと、それが指す別のLispオブジェクトの内容を表す整数です。

2つのオブジェクトobj1obj2がequalの場合、(sxhash obj1)(sxhash obj2)は同じ整数になります。

2つのオブジェクトがequalでない場合、通常はsxhashがreturnする値は異なりますが、常に異なるとは限りません。稀にですが(運次第)、sxhashが同じ結果を与える、2つの異なって見えるオブジェクトに遭遇するかもしれません。

以下は、大の字小文字を区別しない、文字列のキーをもつハッシュテーブルを作成する例です。

(defun case-fold-string= (a b)
  (eq t (compare-strings a nil nil b nil nil t)))
(defun case-fold-string-hash (a)
  (sxhash (upcase a)))

(define-hash-table-test 'case-fold
  'case-fold-string= 'case-fold-string-hash)

(make-hash-table :test 'case-fold)

以下は、事前に定義されたテスト値equalと等価なテストを行なうハッシュテーブルを定義できるという例です。キーは任意のLispオブジェクトで、equalに見えるオブジェクトは、同じキーと判断されます。

(define-hash-table-test 'contents-hash 'equal 'sxhash)

(make-hash-table :test 'contents-hash)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.4 Other Hash Table Functions

以下は、ハッシュテーブルに機能する他の関数です。

Function: hash-table-p table

この関数は、tableがハッシュテーブルオブジェクトの場合は、非nilをreturnします。

Function: copy-hash-table table

この関数は、tableのコピーを作成してreturnします。そのテーブル自体がコピーされたものである場合だけ、キーと値が共有されます。

Function: hash-table-count table

この関数はtable内の実際のエントリー数をreturnします。

Function: hash-table-test table

この関数は、ハッシュを行なう方法と、キーを比較する方法を指定するために、tableが作成されたときに与えられたtestの値をreturnします。Creating Hash Tablesmake-hash-tableを参照してください。

Function: hash-table-weakness table

この関数は、ハッシュテーブルtableに指定されたweakの値をreturnします。

Function: hash-table-rehash-size table

この関数は、tableのrehash-sizeをreturnします。

Function: hash-table-rehash-threshold table

この関数は、tableのrehash-thresholdをreturnします。

Function: hash-table-size table

この関数は、tableの現在の定義されたサイズをreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8 Symbols

シンボル(symbol)は、一意な名前をもつオブジェクトです。このチャプターでは、シンボル、シンボルの構成要素やプロパティーリスト、およびシンボルを作成、インターンする方法を説明します。別のチャプターでは、シンボルを変数として使用したり、関数名として使用する方法が説明されています。VariablesFunctionsを参照してください。シンボルの正確な入力構文については、Symbol Typeを参照してください。

任意のLispオブジェクトがシンボルかどうかを、symbolpでテストできます:

Function: symbolp object

この関数は、objectがシンボルの場合はt、それ以外はnilをreturnします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1 Symbol Components

各シンボルは4つの構成要素(もしくは“セル”)をもち、各構成要素はそれぞれ別のオブジェクトを参照します:

プリント名(print name)

そのシンボルの名前。

値(value)

そのシンボルの、変数としての現在の値。

関数(function)

そのシンボルの関数定義。これはシンボル、キーマップ、キーボードマクロも保持できる。

プロパティーリスト(property list)

そのシンボルのプロパティーリスト。

プリント名のセルは常に文字列を保持し、それを変更することはできません。他の3つのセルには、任意のLispオブジェクトをセットすることができます。

プリントメイのセルは、シンボルの名前となる文字列を保持します。シンボルは、シンボル名によりテキストとして表されるので、2つのシンボルが同じな前をもたないことが重要です。Lispリーダーは、シンボルを読み取るごとに、新たにそれを作成する前に、指定されたシンボルがすでに存在するか調べます。シンボルの名前を得るには、関数symbol-name(Creating and Interning Symbolsを参照してください)を使用します。

値のセルは、シンボルの変数としての値(そのシンボル自身がLisp式として評価されたときに得る値)を保持します。ローカルバインディング(local binding)スコーピングルール(scoping rules)などのような複雑なものを含め、変数がセットされたり、取得される方法については、See section Variablesを参照してください。ほとんどのシンボルは、値として任意のLispオブジェクトをもつことができますが、一部の特別なシンボルは変更できない値をもちます。これらには、nilt、および名前が‘:’で始まる任意のシンボル(キーワード(keyword)と呼ばれます)が含まれます。Variables that Never Changeを参照してください。

関数のセルは、シンボルの関数定義を保持します。実際は、fooの関数セルの中に保管されている関数を意味するとき、“関数foo”といってそれを参照することがよくあります。わたしたちは、必要な土岐だけ、これを明確に区別することにします。関数セルは通常、関数(Functionsを参照してください)か、マクロ(Macrosを参照してください)を保持するために使用されます。しかし、関数セルはシンボル(Symbol Function Indirectionを参照してください)、キーボードマクロ(see section Keyboard Macros)、キーマップ(see section Keymaps)、またはオートロードオブジェクト(Autoloadingを参照してください)を保持するためにも使用できます。シンボルの関数セルの内容を得るには、関数symbol-function (Accessing Function Cell Contentsを参照してください)を使用します。

プロパティーリストのセルは通常、正しくフォーマットされたプロパティーリストを保持するべきです。シンボルのプロパティーリストを得るには、関数symbol-plistを使用します。Symbol Propertiesを参照してください。

巻子失せると値セルが、void(空)のときもあります。voidとは、そのセルがどのオブジェクトも参照していないことを意味します(これは、シンボルvoidを保持することとは異なり、シンボルnilを保持することとも異なります)。voidの関数セルまたは値セルを調べようとすると、結果は‘Symbol's value as variable is void’のようなエラーとなります。

それぞれのシンボルは値セルと関数セルを別個にもつので、変数名と関数名が衝突することはありません。たとえば、シンボルbuffer-file-nameが、値(カレントバッファーでvisitされているファイルの名前)をもち、同様に関数定義(ファイルの名前をreturnする基本関数)をもつことができます:

buffer-file-name
     ⇒ "/gnu/elisp/symbols.texi"
(symbol-function 'buffer-file-name)
     ⇒ #<subr buffer-file-name>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2 Defining Symbols

定義(definition)とは、特別な方法で使用を意図することを宣言する、特別な種類のLisp式です。定義とは通常、シンボルにたいする値を指定するか、シンボルにたいする1つの種類の使用についての意味と、この方法で使用するときのシンボルの意味にたいするドキュメントを指定します。したがって、シンボルを変数として定義した場合、その変数の初期値と、加えてその変数のドキュメントを提供できます。

defvarおよびdefconstは、グローバル変数(global variable) — Lispプログラムの任意の箇所からアクセスできる変数 — として定義するスペシャルフォームです。変数についての詳細は、Variablesを参照してください。カスタマイズ可能な変数を定義するには、defcustom(これはサブルーチンとしてdefvarも呼び出します)を使用します(Customization Settingsを参照してください)。

原則として、最初にシンボルが変数として定義されていなくても、setqで任意のシンボルに値を割り当てることができます。しかし、使用したいそれぞれのグローバル変数にたいして、変数定義を記述するべきです。さもないと、レキシカルスコープ(Scoping Rules for Variable Bindingsを参照してください)が有効なときに変数が評価された場合、あなたのLispプログラムは正しく動作しないでしょう。

defunは、ラムダ式(lambda expression)を生成して、そのシンボルの関数セルにそれを格納することにより、シンボルを関数として定義します。したがって、このシンボルの関数定義は、このラムダ式になります(関数セルの内容を意味する用語“関数定義(function definition)”は、defunがシンボルに関数としての定義を与えるというアイデアに由来します)。Functionsを参照してください。

defmacroは、シンボルをマクロとして定義します。これはマクロオブジェクトを作成して、そのシンボルの関数セルにそれを格納します。シンボルにはマクロと関数を与えることができますが、マクロと関数定義はどちらも関数セルに保持されるのにたいし、関数セルに保持できるのは常にただ1つのLispオブジェクトなので、両方1度にそれを行なうことはできないことに注意してください。Macrosを参照してください。

前に注記したように、Emacs Lispではシンボルを(たとえばdefvarで)変数として定義して、同じシンボルを(たとえばdefunで)関数やマクロとして、両方定義することができます。このような定義は衝突しません。

これらの定義は、プログラミングツールのガイドを果たすこともできます。たとえば、C-h fおよびC-h vコマンドは、関係ある変数、関数、マクロ定義へのリンクを含むヘルプバッファーを作成します。Name Help in The GNU Emacs Manualを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [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を使用する他の例については、Access to Documentation Stringsdocumentationを参照してください。

Function: unintern symbol obarray

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

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

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


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4 Symbol Properties

シンボルは、そのシンボルについての様々な情報を記録するために使用される、任意の数のシンボルプロパティー(symbol properties)をもつことができます。たとえば、シンボルのrisky-local-variableプロパティーがnilの場合は、その変数の名前が、危険なファイルローカル変数(File Local Variablesを参照してください)であることを意味します。

シンボルのプロパティーとプロパティー値はそれぞれ、、シンボルのプロパティーリストセル(Symbol Componentsを参照してください)に、プロパティーリスト形式(Property Listsを参照してください)で格納されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.1 Accessing Symbol Properties

以下の関数は、シンボルプロパティーへのアクセスに使用できます。

Function: get symbol property

この関数は、symbolのプロパティーリスト内の、propertyという名前のプロパティーの値をreturnします。そのようなプロパティーが存在しない場合は、nilをreturnします。したがって、値がnilのときと、プロパティーが存在しない場合の違いはありません。

名前propertyは、eqを使用して既存のプロパティーと比較されるので、任意のオブジェクトはプロパティーとして適正です。

例はputを参照してください。

Function: put symbol property value

この関数は、symbolのプロパティーリストの、プロパティー名propertyvalueを配して、以前のプロパティー値を置き換えます。put関数は、valueをreturnします。

(put 'fly 'verb 'transitive)
     ⇒'transitive
(put 'fly 'noun '(a buzzing little bug))
     ⇒ (a buzzing little bug)
(get 'fly 'verb)
     ⇒ transitive
(symbol-plist 'fly)
     ⇒ (verb transitive noun (a buzzing little bug))
Function: symbol-plist symbol

この関数は、symbolののののプロパティーリストをreturnします。

Function: setplist symbol plist

この関数は、symbolのプロパティーリストを、plistにセットします。plistは通常、適正なプロパティーリストであるべきですが、これは強制ではありません。return値はplistです。

(setplist 'foo '(a 1 b (2 3) c nil))
     ⇒ (a 1 b (2 3) c nil)
(symbol-plist 'foo)
     ⇒ (a 1 b (2 3) c nil)

通常の用途には使用されない、特別なobarray内のシンボルでは、非標準的で方法でプロパティーリストセルを使用することに意味があるかもしれません。実際に、abbrev(Abbrevs and Abbrev Expansionを参照してください)のメカニズムは、これを行なっています。

以下のように、setplistplist-putにより、putを定義できます:

(defun put (symbol prop value)
  (setplist symbol
            (plist-put (symbol-plist symbol) prop value)))
Function: function-get symbol property

この関数は、getと同じですが、symbolが関数エイリアス(function alias)の場合は、実際の関数の名づけるシンボルのプロパティーリストを参照します。Defining Functionsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.2 Standard Symbol Properties

以下に、Emacsで特別な目的のために使用されるシンボルプロパティーをリストします。以下の表で、“名づけられた関数(the named function)”と言うときは、関数名がそのシンボルである関数を意味します。“名づけられた変数(the named variable)”などの場合も、同様です。

:advertised-binding

このプロパティーリストは、名づけられた関数のドキュメントを表示するときの、優先されるキーバインディングを指定します。Substituting Key Bindings in Documentationを参照してください。

char-table-extra-slots

値が非nilの場合は、名づけられた文字テーブル型の追加スロットの数を指定します。Char-Tablesを参照してください。

customized-face
face-defface-spec
saved-face
theme-face

これらのプロパティーは、フェイスの標準のフェイススペック(face specs)、およびフォントスペックsaved-fase、customized-face、themed-faceを記録するために使用されます。これらのプロパティーを直接セットしないでください。これらのプロパティーはdefface、および関連する関数により管理されます。Defining Facesを参照してください。

customized-value
saved-value
standard-value
theme-value

これらのプロパティーは、カスタマイズ可能な変数のstandard-value、saved-value、customized-value(しかし保存はされない)、themed-valueを記録するために使用されます。これらのプロパティーを直接セットしないでください。これらはdefcustom、および関連する関数により管理されます。Defining Customization Variablesを参照してください。

disabled

値が非nilの場合、名づけられた関数はコマンドとして無効になります。Disabling Commandsを参照してください。

face-documentation

値には、名づけられたフェイスのドキュメント文字列が格納されます。これは、deffaceにより自動的にセットされます。Defining Facesを参照してください。

history-length

値が非nilの場合、名づけられたヒストリーリスト変数の、ミニバッファーヒストリーの最大長を指定します。Minibuffer Historyを参照してください。

interactive-form

この値は、名づけられた関数の、インタラクティブ形式です。通常、これを直接セットするべきではありません。かわりに、スペシャルフォームinteractiveを使用してください。Interactive Callを参照してください。

menu-enable

この値は、名づけられたメニューアイテムが、メニュー内で有効であるべきかを決定するための式です。Simple Menu Itemsを参照してください。

mode-class

値がspecialの場合、名づけられたメジャーモードは“special(特別)”です。Major Mode Conventionsを参照してください。

permanent-local

値が非nilの場合、名づけられた変数はバッファーローカル変数となり、変数の値はメジャーモードの変更によりリセットされません。Creating and Deleting Buffer-Local Bindingsを参照してください。

permanent-local-hook

値が非nilの場合、名づけられた変数はメジャーモードを変更したとき、フック変数のローカル値から削除されません。Setting Hooksを参照してください。

pure

値が非nilの場合、名づけられた関数は、副作用の影響を受けないとみなされます。定数の引数で呼び出された場合、コンパイル時に評価することができます。これは、実行時のエラーをコンパイル時へとシフトします。

risky-local-variable

値が非nilの場合、名づけられた変数は、ファイルローカル変数としては危険だとみなされます。File Local Variablesを参照してください。

safe-function

値が非nilの場合、名づけられた関数は、評価において一般的に安全だとみなされます。Determining whether a Function is Safe to Callを参照してください。

safe-local-eval-function

値が非nilの場合、名づけられた関数は、ファイルローカルの評価フォーム内で、安全に呼び出すことができます。File Local Variablesを参照してください。

safe-local-variable

値は、名付けられた変数の、安全なファイルローカル値を決定する関数を指定します。File Local Variablesを参照してください。

side-effect-free

nil値は、関数の安全性(Determining whether a Function is Safe to Callを参照してください)、およびバイトコンパイラーの最適化を決定するために、名づけられた関数が副作用から自由であることを示します。これをセットしないでください。

variable-documentation

nilの場合、それは名づけられた変数のドキュメント文字列を指定します。ドキュメント文字列は、defvarおよび関連する関数により、自動的にセットされます。Defining Facesを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9 Evaluation

Emacs Lispでの式の評価(evaluation)は、Lispインタープリター — 入力としてLispオブジェクトを受け取り、それの式としての値(value as an expression)を計算します — により処理されます。評価を行なう方法は、そのオブジェクトのデータ型に依存し、それはこのチャプターで説明するルールにより行なわれます。インタープリターは、プログラムの一部を評価するために自動的に実行されますが、Lisp基本関数のevalを通じて、明示的に呼び出すこともできます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1 Introduction to Evaluation

Lispインタープリター(またはLispエバリュエーター)は、Emacsの一部で、与えられた式の値を計算します。Lispで記述された関数が呼び出されるとき、エバリュエーターはその関数のbody(本文)の中の式を評価することにより、その関数の値を計算します。したがって、Lispプログラムを実行するとは、実際にはLispインタープリターを実行することを意味します。

評価されることを意図したLispオブジェクトは、フォーム(form)、または式(expression)と呼ばれます4。フォームはデータオブジェクトであり、単なるテキストではないというのは、Lisp風の言語と、通常のプログラミング言語との間にある、基本的な相違の1つです。任意のオブジェクトを評価できますが、実際に評価される事が非常に多いのは数字、シンボル、リスト、文字列です。

以降のセクションでは、各種フォームにたいして、それを評価することが何を意味するかの詳細を説明します。

Lispフォームを読み取り、それからそのフォームを評価するのは、非常に一般的なアクティビティーですが、読み取りと評価は別のアクティビティーであり、どちらか一方を単独で処理することができます。読み取りだけでは、何も評価されません。読み取りはLispオブジェクトのプリント表現を、そのオブジェクト自体に変換します。このオブジェクトは評価されるべきフォームなのか、そのれともまったく違う目的をもつかを指定するのは、readの呼び出し元の役目ですInput Functionsを参照してください。

評価とは再帰的な処理であり、あるフォームを評価することにより、そのフォームの一部が評価されるといったことがよくあります。たとえば、(car x)のような関数呼び出し(function call)のフォームを評価する場合、Emacsは最初にその引数(サブフォームx)を評価します。引数を評価した後、Emacsはその関数(car)を実行(executes)します。その関数がLispで記述されている場合は、関数のbody(本文)を評価することにより、実行が行なわれます(しかし、この例で使用しているcarはLisp関数ではなく、Cで実装された基本関数です)。関数と関数呼び出しについての情報は、Functionsを参照してください。

評価は、環境(environment)と呼ばれるコンテキストの内部で行なわれます。環境は、すべてのLisp変数(Variablesを参照してください)のカレント値とバインディングにより構成されます。5フォームが新たなバインディングを作成することなく、変数を参照するとき、その変数はカレントの環境により与えられる値に評価されます。フォームの評価は、変数のバインディングにより、一時的にその環境を変更することもあります(Local Variablesを参照してください)。

フォームの評価が、永続する変更を行なうこともあります。これらの変更は、副作用(side effects)と呼ばれます。副作用を生成するフォームの例は、(setq foo 1)です。

コマンドキー解釈にたいする評価と混同しないでください。エディターのコマンドループは、アクティブなキーマップを使用して、キーボード入力をコマンド(インタラクティブに呼び出すことができる関数)に変換してから、そのコマンドを実行するためにcall-interactivelyを使用します。そのコマンドはLispで記述されている場合、コマンドの実行は通常、評価を伴います。しかし、このステップはコマンドキー解釈の一部とは考えません。Command Loopを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 Kinds of Forms

評価される事を意図したLispオブジェクトは、フォーム(form)または式(expression))と呼ばれます。Emacsがフォームを評価する方法は、フォームのデータ型に依存します。Emacsは、3種の異なるフォーム — シンボル、リスト、および“その他すべての型” — を持ち、それらは評価される方法は異なります。このセクションでは、まず最初は自己評価フォームの“その他すべての型”から開始して、3つの種類をすべて1つずつ説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.1 Self-Evaluating Forms

自己評価フォーム(self-evaluating form)は、リストやシンボルではない、任意のフォームです。自己評価フォームは、フォーム自身を評価します。評価の結果は、評価されたのと同じオブジェクトです。したがって、数字の25は25に評価され、文字列"foo"は文字列"foo"に評価されます。同様に、ベクターの評価では、ベクターの要素の評価は起こりません — 内容が変更されずに同じベクターがreturnされます。

'123               ; 評価されずに表示される数字。
     ⇒ 123
123                ; 通常どおり評価され、同じものがreturnされる。
     ⇒ 123
(eval '123)        ; “手動”による評価 — 同じものがreturnされる。
     ⇒ 123
(eval (eval '123)) ; 2度評価しても何も変わらない。
     ⇒ 123

事項評価されるという事実による利点から、数字、文字、文字列、そしてベクターでさえ、Lispコード内で記述されるのは一般的です。しかし、入力構文がない型にたいしてこれを行なうのは極めて異例です。なぜなら、これらをテキスト的に記述する方法がないからです。Lispプログラムを使用して、これらの型を含むLisp式を構築するのは、可能です。以下は例です:

;; バッファーオブジェクトを含む式を構築する。
(setq print-exp (list 'print (current-buffer)))
     ⇒ (print #<buffer eval.texi>)
;; それを評価する。
(eval print-exp)
     -| #<buffer eval.texi>
     ⇒ #<buffer eval.texi>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.2 Symbol Forms

シンボルが評価されるときは、変数として扱われます。それが値をもつ場合、結果はその変数の値になります。そのシンボルが変数としての値をもたない場合、Lispインタープリターはエラーをシグナルします。変数の使用法についての情報は、Variablesを参照してください。

以降の例では、setqでシンボルに値をセットしています。その後シンボルを評価してから、その値をsetqに戻します。

(setq a 123)
     ⇒ 123
(eval 'a)
     ⇒ 123
a
     ⇒ 123

シンボルniltは特別に扱われるので、nilの値は常にnilになり、tの値は常にtになります。これらに他の値をセットしたり、他の値にバインドすることはできません。したがって、この2つのシンボルは、(たとえevalがそれらを他の任意のシンボルと同じように扱うとはいえ)自己評価フォームと同じように振る舞います。名前が‘:’で始まるシンボルも、同じ方法で自己評価されます。そして、(通常は)値を変更できない点も同じです。Variables that Never Changeを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.3 Classification of List Forms

空ではないリストフォームは、関数呼び出し、マクロ呼び出し、スペシャルフォームのいずれかで、それは1番目の引数にしたがいます。これら3種のフォームは、以下で説明するように、異なる方法で評価されます。残りの要素は関数、マクロ、またはスペシャルフォームにたいする引数(arguments)を構成します。

空ではないリストを評価する最初のステップは、1番目の要素の確認です。この要素は単独で、そのリストがどの種類のフォームか、そして残りの引数をどのように処理するがを決定します。SchemeのようなLisp方言とは異なり、1番目の要素は評価されません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.4 Symbol Function Indirection

リストの最初の要素がシンボルの場合、評価はそのシンボルの関数セルを調べて、元のシンボルの代わりに、関数セルの内容を使用します。その内容が他のシンボルの場合、シンボルではないものが得られるまで、このプロセスが繰り返されます。このプロセスをシンボル関数インダイレクション(symbol function indirection: indirectionは間接の意)と呼びます。シンボル関数インダイレクションについての情報は、Naming a Functionを参照してください。

このプロセスの結果、シンボルの関数競るが同じシンボルを参照する場合、無限ループを起こす可能性があります。それ以外は、最終的には非シンボルにたどりつき、これは関数か、他の適切なオブジェクトであるはずです。

より正確に言うと、それはLisp関数(ラムダ式)、バイトコード関数、基本関数、Lispマクロ、スペシャルフォーム、またはオートロードオブジェクトであるべきです。これらの型のそれぞれについては、以降のセクションで説明します。これらの型以外のオブジェクトの場合、emacsはinvalid-functionエラーをシグナルします。

以下の例は、シンボルインダイレクションのプロセスを説明するものです。わたしたちは、シンボルの関数セルに関数をセットするのにfset、関数セルの内容(Accessing Function Cell Contentsを参照してください)を得るためにsymbol-functionを使用します。具体的に言うと、firstの関数セルにシンボルcarを格納し、シンボルfirstersteの関数セルに格納します。

;; この関数セルのリンクを構築する:
;;   -------------       -----        -------        -------
;;  | #<subr car> | <-- | car |  <-- | first |  <-- | erste |
;;   -------------       -----        -------        -------
(symbol-function 'car)
     ⇒ #<subr car>
(fset 'first 'car)
     ⇒ car
(fset 'erste 'first)
     ⇒ first
(erste '(1 2 3))   ; ersteにより参照される関数を呼び出す。
     ⇒ 1

対照的に、以下の例はシンボル関数インダイレクションを使用せずに関数を呼び出します。なぜなら、1番目の要素はシンボルではなく、無名Lisp関数(anonymous Lisp function)だからです。

((lambda (arg) (erste arg))
 '(1 2 3))
     ⇒ 1

関数自身を実行すると、その関数のbodyを評価します。これは、ersteを呼び出すとき、シンボル関数インダイレクションが行なわれます。

このフォームが使用されるのは稀で、今では推奨されません。かわりに以下のように記述するべきです:

(funcall (lambda (arg) (erste arg))
         '(1 2 3))

または単に

(let ((arg '(1 2 3))) (erste arg))

ビルトイン関数のindirect-functionは、明示的にシンボル関数インダイレクションを処理するための、簡単な方法を提供します。

Function: indirect-function function &optional noerror

この関数は、functionが意味するものを、関数としてreturnします。functionがシンボルの場合は、functionの関数定義を探して、その値で最初からやり直します。functionがシンボルでない場合は、function自身をreturnします。

この関数は、最後のシンボルがバインドされておらず、オプション引数noerrorが省略されているかnilの場合は、void-functionエラーをシグナルします。それ以外は、noerrorが非nilの場合は、最後のシンボルがバインドされていなければnilをreturnします。

特定のシンボル内にループがある場合、この関数はcyclic-function-indirectionエラーをシグナルします。

以下は、Lispでindirect-functionを定義できるという例です:

(defun indirect-function (function)
  (if (symbolp function)
      (indirect-function (symbol-function function))
    function))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.5 Evaluation of Function Forms

リストの1番目の要素がLispの関数オブジェクト。バイトコードオブジェクト、基本関数オブジェクトと評価された場合、そのリストは関数呼び出し(function call)になります。たとえば、以下は関数+を呼び出します:

(+ 1 x)

関数呼び出しを評価する最初のステップは、そのリストの残りの要素を左から右に評価します。結果は引数の実際の値で、リストの各要素にたいして1つの値となります。次のステップは、関数apply(Calling Functionsを参照してください)を使用して、引数のリストでその関数を呼び出します。関数がLispで記述されている場合、引数はその関数の引数変数にバインドするために使用されます。その後、関数body内のフォームが順番に評価され、listのbodyフォームの値は、関数呼び出しの値になります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.6 Lisp Macro Evaluation

リストの最初の要素がマクロオブジェクトと評価された場合、そのリストはマクロ呼び出し(macro call)になります。マクロ呼び出しが評価されるとき、リストの残りの要素は、最初は評価されません。そのかわり、これらの要素自体が、マクロの引数に使用されます。そのマクロ定義は、これは元のフォームの場所で評価される、置き換えのフォームを計算します。これは、マクロの展開(expansion)と呼ばれます。展開した結果は、任意の種類のフォーム — 自己評価定数、シンボル、リストになります。展開した結果自体がマクロ呼び出しの場合、結果が他の種類のフォームになるまで、繰り返し展開処理が行なわれます。

通常のマクロ展開は、その展開形を評価することにより終了します。しかし、他のプログラムもマクロ呼び出しを展開し、それらが展開形を評価するかもしれないし、評価しないかもしれないので、そのマクロ展開がすぐに、または最終的に評価される必要がない場合があります。

引き数式は通常、マクロ展開の計算の一部としては評価されませんが、展開の部分として現れるので、展開形が評価されるとき計算されます。

たとえば、以下のようなマクロ定義が与えられたとします:

(defmacro cadr (x)
  (list 'car (list 'cdr x)))

(cadr (assq 'handler list))のような式はマクロ呼び出しであり、展開形は以下のようになります:

(car (cdr (assq 'handler list)))

引数(assq 'handler list)が、展開形に含まれることに注意してください。

Emacs Lispマクロの完全な説明は、Macrosを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.7 Special Forms

スペシャルフォーム(special form)は特別だとマークされた基本関数で、その引数のすべては評価されません。もっともスペシャルなフォームは、制御構造の定義や、変数バインディングの処理など、関数ではできないことを行ないます。

スペシャルフォームはそれぞれ、どの引数が評価されて、どの引数が評価されないかについて、独自のルールをもちます。特定の引数が評価されるかどうかは、他の引数を評価した結果に依存します。

式の最初のシンボルがスペシャルフォームの場合、その式はそのスペシャルフォームのルールにしたがう必要があります。それ以外では、Emacsの挙動は(たとえクラッシュしなくても)定義されていません。たとえば((lambda (x) x . 3) 4)は、lambdaで始まるサブ式を含みますが、これは適正なlambda式ではないので、Emacsはエラーをシグナルするか、3、または4、またはnil、もしかしたら他の挙動を示すかもしれません。

Function: special-form-p object

この述語は、引数がスペシャルフォームかをテストし、スペシャルフォームならt、それ以外はnilをreturnします。

以下に、Emacs Lispのスペシャルフォームすべてと、それらがどこで説明されているかのリファレンスとともに、アルファベット順でリストします。

and

see section Constructs for Combining Conditions

catch

see section Explicit Nonlocal Exits: catch and throw

cond

see section Conditionals

condition-case

see section Writing Code to Handle Errors

defconst

see section Defining Global Variables

defvar

see section Defining Global Variables

function

see section Anonymous Functions

if

see section Conditionals

interactive

see section Interactive Call

lambda

see section Lambda Expressions

let
let*

see section Local Variables

or

see section Constructs for Combining Conditions

prog1
prog2
progn

see section Sequencing

quote

see section Quoting

save-current-buffer

see section The Current Buffer

save-excursion

see section Excursions

save-restriction

see section Narrowing

setq

see section Setting Variable Values

setq-default

see section Creating and Deleting Buffer-Local Bindings

track-mouse

see section Mouse Tracking

unwind-protect

see section Nonlocal Exits

while

see section Iteration

Common Lispに関する注意: ここで、GNU Emacsのスペシャルフォームと、Common Lispのスペシャルフォームを比較してみます。setqifcatchは、Emacs LispとCommon Lispの両方でスペシャルフォームです。save-excursionはEmacs Lispではスペシャルフォームですが、Common Lispには存在しません。throwはCommon Lispではスペシャルフォーム(なぜなら複数の値をthrowできなければならない)ですが、Emacs Lispでは(複数の値をもたない)関数です。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.8 Autoloading

オートロード(autoload)機能により、関数定義がだEmacsにロードされていない関数(またはマクロ)を呼び出すことができます。オートロードは、定義がどのファイルに含まれるかを指定します。オートロードオブジェクトがシンボルの関数定義にある場合、関数としてそのシンボルを呼び出すことにより、自動的に指定されたファイルがロードされます。その後、ファイルからロードされた実際の定義を呼び出します。シンボル内の関数定義としてオートロードオブジェクトをアレンジする方法は、Autoloadで説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3 Quoting

スペシャルフォームquoteは、単一の引数を、記述されたとおり、評価せずにreturnします。これはプログラムに、自己評価オブジェクトではない、定数シンボルや定数リストを含める方法を提供します(数字、文字列、ベクターのような自己評価オブジェクトをクォートする必要はありません)。

Special Form: quote object

このスペシャルフォームは、評価せずにobjectをreturnします。

プログラム中でquoteはよく使用されるので、Lispはそれにたいする便利な入力構文を提供します。アポストロフィー文字(‘'’)に続けてLispオブジェクト(の入力構文)を記述すると、それは1番目の要素がquoteで、2番目の要素がそのオブジェクトであるリストに展開されます。したがって、入力構文'xは、(quote x)の略記になります。

以下に、quoteを使用した式の例をいくつか示します:

(quote (+ 1 2))
     ⇒ (+ 1 2)
(quote foo)
     ⇒ foo
'foo
     ⇒ foo
''foo
     ⇒ (quote foo)
'(quote foo)
     ⇒ (quote foo)
['foo]
     ⇒ [(quote foo)]

他のクォート構成には、コンパイル用にLispで記述された無名のラムダ式の元になるfunction(Anonymous Functionsを参照してください)、および、リストを計算して置き換える際に、リストの一部だけをクォートするのに使用される‘`’(Backquoteを参照してください)があります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4 Backquote

バッククォート構成(backquote constructs)を使用することにより、リストをクォートして、そのリストのある要素を選択的に評価することができます。もっとも簡単な使い方では、スペシャルフォームquoteと同じです (前のセクションで説明しています。Quotingを参照してください)。 たとえば、以下の2つのフォームは同じ結果を生みます:

`(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)
'(a list of (+ 2 3) elements)
     ⇒ (a list of (+ 2 3) elements)

バッククォートする引数の内側でスペシャルマーカー‘,’を使用すると、それは値が定数でないことを示します。Emacs Lispエバリュエーターは‘,’がついた引数を放火して、リスト構造内にその値を配します:

`(a list of ,(+ 2 3) elements)
     ⇒ (a list of 5 elements)

,’による置き換え、リスト構造のより深いレベルでも使用できます。たとえば:

`(1 2 (3 ,(+ 4 5)))
     ⇒ (1 2 (3 9))

スペシャルマーカー‘,@’を使用すれば、評価された値を結果リストに継ぎ足す(splice)こともできます。継ぎ足されたリストの要素は、結果リスト内の他の要素を同じレベルになります。‘`’を使用しない等価なコードは、しばしば読むのが困難です。以下にいくつかの例を示します:

(setq some-list '(2 3))
     ⇒ (2 3)
(cons 1 (append some-list '(4) some-list))
     ⇒ (1 2 3 4 2 3)
`(1 ,@some-list 4 ,@some-list)
     ⇒ (1 2 3 4 2 3)

(setq list '(hack foo bar))
     ⇒ (hack foo bar)
(cons 'use
  (cons 'the
    (cons 'words (append (cdr list) '(as elements)))))
     ⇒ (use the words foo bar as elements)
`(use the words ,@(cdr list) as elements)
     ⇒ (use the words foo bar as elements)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.5 Eval

ほとんどの場合、実行されるプログラム内に出現することにより、フォームは自動的に評価されます。稀に、実行時 — たとえば編集されているテキストや、プロパティーリストから取得したフォームを読み取った後 — に計算されるように、フォームを評価するコードを記述する必要があるかもしれません。このようなときは、eval関数を使用します。evalが不必要だったり、かわりに他の何かを使用すべきときが、しばしばあります。たとえば、変数から値を取得するには、evalも機能しますが、symbol-valueのほうが適しています。evalで評価するためにプロパティーリストに式を格納するより、かわりにfuncallに渡すように関数を格納した方がよいでしょう。

このセクションで説明する関数と変数は、フォームの評価、評価処理の制限の指定、最後にreturnされた値の記録を行なうものです。ファイルのロードでも評価が行なわれます(Loadingを参照してください)。

データ構造に式を格納してそれを評価するより、データ構造に関数を格納して、それをfuncallapplyで呼び出すほうが、より明解かつ柔軟です。関数を使用することにより、引数に情報を渡す能力が提供されます。

Function: eval form &optional lexical

これは、式を評価する、基本的な関数です。この関数は、カレント環境内でformを評価して、その結果をreturnします。formオブジェクトの型は、それが評価される方法を決定します。Kinds of Formsを参照してください。

引数lexicalは、ローカル変数にたいするスコープ規則(Scoping Rules for Variable Bindingsを参照してください)を指定します。これが省略されるかnilの場合、デフォルトのダイナミックスコープ規則を使用してformを評価することを意味します。tの場合は、レキシカルスコープ規則が使用されることを意味します。lexicalの値には、レキシカルバインディングにたいする特定のレキシカル環境(lexical environment)を指定する、空ではないalistも指定できます。しかし、この機能はEmacs Lispデバッガーのような、特別な目的にたいしてのみ有用です。Lexical Bindingを参照してください。

evalは関数なので、eval呼び出しに現れる引数式は2回 — 1度はevalが呼び出される前の準備、そしてeval関数自身によりもう1度 — 評価されます。以下は例です:

(setq foo 'bar)
     ⇒ bar
(setq bar 'baz)
     ⇒ baz
;; evalが引数fooを受け取る。
(eval 'foo)
     ⇒ bar
;; evalが、fooの値である、引数barを受け取る。
(eval foo)
     ⇒ baz

evalにより現在アクティブな呼び出しの数は、max-lisp-eval-depthに制限されます(以下参照)。

Command: eval-region start end &optional stream read-function

この関数は、カレントバッファー内の、位置startendで定義されるリージョン内のフォームを評価します。この関数はそのリージョンからフォームを読み取り、それらにたいしevalを呼び出します。これは、リージョンの最後に達するまで、または処理されないエラーがシグナルされるまで行なわれます。

デフォルトでは、eval-regionは何の出力も生成しません。しかし、streamが非nilの場合、出力関数(Output Functionsを参照してください)で生成された任意の出力、同様にリージョン内の式を評価した結果の値は、streamを使用してプリントされます。Output Streamsを参照してください。

read-functionが非nilの場合、readのかわりに1つずつ式を読み取るために使用する関数を指定します。これは、入力を読み取るストリームを指定する、1つの引数で呼び出される関数です。この関数を指定するために変数load-read-function(How Programs Do Loadingを参照してください)も使用できますが、引数read-functionを使用するほうが確実です。

eval-regionはポイントを移動しません。つねにnilをreturnします。

Command: eval-buffer &optional buffer-or-name stream filename unibyte print

この関数はeval-regionと似ていますが、引数は異なるオプション機能を提供します。eval-bufferは、バッファーbuffer-or-nameのアクセス可能な部分全体を処理します。buffer-or-nameにはバッファー名(文字列)を指定でき、nil(または省略)のときはカレントバッファーを意味します。streamnilかつprintが非nilでない場合、eval-regionのようにstreamが使用されます。この場合、式の評価による結果の値は依然として破棄されますが、出力関数による出力はエコーエリアにプリントされます。filenameは、load-history(Unloadingを参照してください)に使用されるファイル名で、デフォルトはbuffer-file-name(Buffer File Nameを参照してください)です。unibyteが非nilの場合、可能な限りreadは文字列をユニコードに変換します。

eval-current-bufferは、このコマンドのエイリアスです。

User Option: max-lisp-eval-depth

この変数は、エラー(エラーメッセージは"Lisp nesting exceeds max-lisp-eval-depth")がシグナルされる前に、evalapplyfuncallの呼び出しで許される最大の深さを定義します。

制限を超えたときのエラーをもつこの制限は、Emacs Lispで誤って定義された関数による無限再帰を避ける方法の1つです。max-lisp-eval-depthの値を過大に増加させた場合、そのようなコードはかわりにスタックオーバーフローを起こすでしょう。

たとえば、Lisp式に記述された関数の呼び出し、関数呼び出しの引数と、関数bodyフォームにたいする再帰評価、Lispコード内での明示的な呼び出しなどにたいして、深さ制限を数えるために、内部的にevalapplyfuncallを使用します。

この変数のデフォルト値は400です。この値を100未満にセットした場合、値が与えられた値に達すると、Lispはそれを100にリセットします。空きが少ない場合、デバッガー自身を実行するために空きが必要になるので、Lispデバッガーに入ったときは、この値が増加されます。

max-specpdl-sizeはネストの他の制限を提供します。Local Variablesを参照してください。

Variable: values

この変数の値は、読み取り、評価、プリントを行なった標準的なEmacsコマンドにより、バッファー(ミニバッファーを含む)からreturnされる値のリストです(これには*ielm*バッファーでの評価や、lisp-interaction-modeでのC-jを使用した評価は含まれないことに注意してください)。要素の順番は、もっとも最近のものが最初になります。

(setq x 1)
     ⇒ 1
(list 'A (1+ 2) auto-save-default)
     ⇒ (A 3 t)
values
     ⇒ ((A 3 t) 1 …)

この変数は、最近評価されたフォームの値を後で参照するのに便利です。values自体の値をプリントするのは、それがおそらく非常に長くなるので、通常は悪いアイデアです。かわりに、以下のように特定の要素を調べます:

;; もっとも最近評価された結果を参照する。
(nth 0 values)
     ⇒ (A 3 t)
;; これは新たな要素をputするので、
;;   すべての要素が1つ後に移動する。
(nth 1 values)
     ⇒ (A 3 t)
;; これは次に新しい、この例の前の次に新しい要素を取得する。
(nth 3 values)
     ⇒ 1

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10 Control Structures

Lispプログラムは、一連の式(expressions)、あるいはフォーム(forms)(Kinds of Formsを参照してください)により形成されます。これらのフォームの実行順は、それらを制御構造(control structures)で囲むことにより制御します。制御構造とは、その制御構造が含むフォームをいつ、どのような条件で、何回実行するかを制御する、スペシャルフォームです。

もっとも単純な実行順は、1番目はa、2番目はb、...という、シーケンシャル実行(sequential execution: 順番に実行)です。これは、関数のbody内の連続する複数のフォームや、Lispコードのファイル内のトップレベルを記述したときに発生します — つまり、フォームは記述した順に実行されます。わたしたちはこれをテキスト順(textual order)と呼びます。たとえば、関数のbodyが2つのフォームabから構成される場合、関数の評価は、最初にaを評価し、次にbを評価します。bを評価した結果が、その関数の値となります。

明示的に制御構造を使用することにより、シーケンシャルではない順番での実行が可能になります。

Emacs Lispは、他の様々な順序づけ、条件、繰り返し、(制御された)ジャンプを含む、複数の種類の制御構造を提供し、以下ではそれらすべてを記述します。ビルトインの制御構造は、制御構造のサブフォームが評価される必要がなかったり、順番に評価される必要がないので、スペシャルフォームです。独自の制御構造を構築するためにマクロを使用することができます(Macrosを参照してください)。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1 Sequencing

フォームが出現する順番に評価するのは、あるフォームから別のフォームに制御を渡す、もっとも一般的な制御です。関数のbodyのような、あるコンテキストにおいては、自動的にこれが行なわれます。他の場所では、これを行なうために制御構造を使用しなければなりません。Lispで一単純な制御構造は、prognです。

スペシャルフォームprognは、以下のようなものです:

(progn a b c …)

これは、順番にabc、...を実行するよう指定します。これらはprognフォームのbodyと呼ばれます。body内の最後のフォームの値が、progn全体の値になります。(progn)nilをreturnします。

初期のLispでは、prognは、連続で複数のフォームを実行して最後のフォームの値を使用する、唯一の方法でした。しかしプログラマーは、関数のbodyの、(その時点では)1つのフォームだけが許される場所で、prognを使用する必要が多いことに気づきました。そのため、関数のbodyを“暗黙のprogn”にして、prognのbodyのように複数のフォームを記述出きるようにしました。他の多くの制御構造も、同様に暗黙のprognを含みます。結果として、昔ほどprognは多用されなくなりました。現在では、prognが必要になるのは、unwind-protectandorifthenパートの中がほとんどです。

Special Form: progn forms…

このスペシャルフォームは、formsのすべてをテキスト順に評価して、のフォームの結果をreturnします。

(progn (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
⇒ "The third form"

他の2つの構成は、一連のフォームを同様に評価しますが、異なる値をreturnします:

Special Form: prog1 form1 forms…

このスペシャルフォームは、form1formsのすべてをテキスト順に評価して、form1の結果をreturnします。

(prog1 (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
⇒ "The first form"

以下の例は、変数xのリストから1番目の要素を削除して、削除した1番目の要素の値をreturnします:

(prog1 (car x) (setq x (cdr x)))
Special Form: prog2 form1 form2 forms…

このスペシャルフォームは、form1form2、その後のformsのすべてをテキスト順で評価して、form2の結果をreturnします。

(prog2 (print "The first form")
       (print "The second form")
       (print "The third form"))
     -| "The first form"
     -| "The second form"
     -| "The third form"
⇒ "The second form"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2 Conditionals

条件による制御構造は、候補の中から選択を行ないます。Emacs Lispは4つの条件フォームをもちます。ifは他の言語のものとほとんど同じです。whenunlessは、ifの変種です。condは一般化されたcase命令です。

Special Form: if condition then-form else-forms…

ifは、conditionの値にもとづいて、then-formelse-formsを選択します。評価されたconditionが非nilの場合は、then-formが評価されて、その結果がreturnされます。それ以外は、else-formsがテキスト順に評価されて、最後のフォームの値がreturnされます(ifelseパートは、暗黙のprognの例です。Sequencingを参照してください)。

conditionの値がnilで、else-formsが与えられない場合、ifnilをreturnします。

選択されなかったブランチは決して評価されない — 無視される — ので、ifはスペシャルフォームです。したがって、以下の例ではprintは呼び出されることはないので、trueはプリントされません。

(if nil
    (print 'true)
  'very-false)
⇒ very-false
Macro: when condition then-forms…

これは、else-formsがなく、複数のthen-formsがあるかもしれない、ifの変種です。特に、

(when condition a b c)

は以下と完全に等価です

(if condition (progn a b c) nil)
Macro: unless condition forms…

これはthen-formがない、ifの変種です:

(unless condition a b c)

は以下と完全に等価です

(if condition nil
   a b c)
Special Form: cond clause…

condは、任意の数の候補から選択を行ないます。cond内の各clauseは、リストでなければなりません。このリストのCARconditionで、(もしあれば)残りの要素はbody-formsです。したがって、条項は以下のようになります:

(condition body-forms…)

condは、各条項のconditionを評価することにより、テキスト順で条項を試験します。conditionの値が非nilの場合、その条項は“成り立ち”ます。その後、condは、その条項のbody-formsを評価して、body-formsの最後の値をreturnします。残りの条項は無視されます。

conditionの値がnilの場合、その条項は“成り立たず”、condは次の条項に移動して、その条項のconditionを試験します。

以下のようなものも、条項になります:

(condition)

conditionがテストされたときに非nilなら、condフォームはconditionの値をreturnします。

すべてのconditionnilに評価された場合 — つまりすべての条項が不成立の場合、condnilをreturnします。

以下の例は4つの条項をもち、xの値が数字か、文字列化、バッファーか、シンボルかをテストします:

(cond ((numberp x) x)
      ((stringp x) x)
      ((bufferp x)
       (setq temporary-hack x) ; 1つの条項に
       (buffer-name x))        ; 複数bodyフォーム。
      ((symbolp x) (symbol-value x)))

前の条項が不成立のとき、最後の条項を実行したいときがよくあります。これを行なうには、(t body-forms)のように、conditionの最後の条項にtを使用します。フォームttに評価され、決してnilにならないので、この条項が不成立になることはなく、最終的にcondはこの条項に到達します。たとえば:

(setq a 5)
(cond ((eq a 'hack) 'foo)
      (t "default"))
⇒ "default"

このcond式は、aの値がhackの場合はfoo、それ以外は文字列"default"をreturnします。

任意の条件構成は、condifで表すことができます。したがって、どちらを選択するかは、スタイルの問題です、たとえば:

(if a b c)
≡
(cond (a b) (t c))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.1 Pattern matching case statement

特定の値を、可能なさまざまの場合にたいして比較するには、マクロpcaseが便利です。これは以下のフォームをとります:

(pcase exp branch1 branch2 branch3 …)

branchは、(upattern body-forms…)というフォームです。

これは最初にexpを評価してから、どのbranchを使用するか、その値を各upatternと比較して、その後で対応するbody-forms実行します。一般的なのは、少数の異なる定数値を区別するために使用される場合です:

(pcase (get-return-code x)
  (`success       (message "Done!"))
  (`would-block   (message "Sorry, can't do it now"))
  (`read-only     (message "The shmliblick is read-only"))
  (`access-denied (message "You do not have the needed rights"))
  (code           (message "Unknown return code %S" code)))

最後の条項のcodeは、(get-return-code x)からreturnされた値にバインドされる変数です。

もっと複雑な例として、以下のような小さな式言語のための単純なインタープリターを示します(この例ではレキシカルバインディングが必要なことに注意してください):

(defun evaluate (exp env)
  (pcase exp
    (`(add ,x ,y)       (+ (evaluate x env) (evaluate y env)))
    (`(call ,fun ,arg)  (funcall (evaluate fun env) (evaluate arg env)))
    (`(fn ,arg ,body)   (lambda (val)
                          (evaluate body (cons (cons arg val) env))))
    ((pred numberp)     exp)
    ((pred symbolp)     (cdr (assq exp env)))
    (_                  (error "Unknown expression %S" exp))))

`(add ,x ,y)は、expがシンボルaddで始まる3要素のリストかチェックして、その後2番目と3番目の要素を抽出し、それらを変数xyにバインドするパターンです。(pred numberp)expが数字かを単にチェックし、_はすべてのものにマッチするcatch-allパターンです。

以下に、いくつかの例を評価した結果とともに示します:

(evaluate '(add 1 2) nil)                 ;=> 3
(evaluate '(add x y) '((x . 1) (y . 2)))  ;=> 3
(evaluate '(call (fn x (add 1 x)) 2) nil) ;=> 3
(evaluate '(sub 1 2) nil)                 ;=> error

pcaseに関係する2種類のパターンがあり、それらはU-patternsQ-patternsと呼ばれます。上述のupatternはU-patternsで、以下の形式をもつことができます:

`qpattern

これは、もっとも一般的なパターンの1つです。このパターンの意図は、バッククォートマクロの模倣です。このパターンは、バッククォート式により構築されるような値にマッチします。わたしたちが行なうのは値の構築ではなくパターンマッチングなので、非クォートは式をどこに挿入するか示すのではなく、かわりにその位置で値にマッチすべき1つのU-patternを指定します。

より具体的には、Q-patternは以下のフォームをもつことができます:

(qpattern1 . qpattern2)

このパターンは、carqpattern1cdrpattern2にマッチする、任意のコンスセルにマッチします。

atom

このパターンは、atomequalな任意のアトムにマッチします。

,upattern

このパターンは、upatternにマッチする任意のオブジェクトにマッチします。

symbol

U-pattern内の単なるシンボルはすべてにマッチし、さらにマッチした値にそのシンボルをバインドするので、body-formsや皇族のパターンから、それを参照することができます。

_

このパターン — いわゆるdon’t careパターン — はシンボルパターンと同様、すべてのものにマッチしますが、シンボルパターンとは異なり、変数へのバインドを行ないません。

(pred pred)

このパターンは、マッチされるオブジェクトで関数predが呼び出したとき、非nilをreturnするものにマッチします。

(or upattern1 upattern2…)

このパターンは、引数のパターンから最初に成立したパターンにマッチします。すべての引数パターンは、同じ変数にバインドされるべきです。

(and upattern1 upattern2…)

このパターンは、すべての引数パターンが成立したときだけマッチします。

(guard exp)

このパターンは調べられるオブジェクトを無視して、expが非nilに評価されたときは成立、それ以外は不成立となります。これは通常、andパターンの内部で使用されます。たとえば、(and x (guard (< x 10)))は10より小さい任意の数字にマッチして、それを変数xにバインドします。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3 Constructs for Combining Conditions

このセクションは、複雑な条件を表現するために、ifcondとともによく使用される3つの構成を記述します。andorの構成は、ある種の複数条件の構成として、個別に使用することもできます。

Function: not condition

この関数は、conditionが偽であることをテストします。この関数はconditionnilの場合はt、それ以外はnilをreturnします。関数notnullと等価で、わたしたちは空のリストをテストする場合は、nullの使用を推奨します。

Special Form: and conditions…

スペシャルフォームandは、すべてのconditionsが真かどうかをテストします。この関数は、conditionsを記述された順に1つずつ評価することにより機能します。

あるconditionsnilに評価された場合、残りのconditionsに関係なく、andnilをreturnしなければなりません。この場合、andは即座にnilをreturnし、残りのconditionsは無視されます。

すべてのconditionsが非nilの場合、それらの最後の値がandフォームの値になります。conditionsのない単独の(and)は、tをreturnします。なぜなら、すべてのconditionsが非nilとなるので(考えてみてください。そうでないのはどれですか?)、これは適切です。

以下に例を示します。1番目の条件は整数1をretuenし、これはnilではありません。同様に2番目の条件は整数2をreturnし、これもnilではありません。3番目の条件はnilなので、のこりの条件が評価されることは決してありません。

(and (print 1) (print 2) nil (print 3))
     -| 1
     -| 2
⇒ nil

以下は、andを使用した、より現実的な例です:

(if (and (consp foo) (eq (car foo) 'x))
    (message "foo is a list starting with x"))

(consp foo)nilをreturnした場合、(car foo)は実行されないので、エラーにならないことに注意してください。

ifcondのどちらかを使用して、and式を記述することもできます。以下はその方法です:

(and arg1 arg2 arg3)
≡
(if arg1 (if arg2 arg3))
≡
(cond (arg1 (cond (arg2 arg3))))
Special Form: or conditions…

スペシャルフォームorは、少なくとも1つのconditionsが真かどうかをテストします。この関数は、すべてのconditionsを1つずつ、記述された順に評価することにより機能します。

あるconditionsが非nil値に評価された場合、orの結果は非nilでなければなりません。この場合、orは即座にreturnし、残りのconditionsは無視されます。この関数がreturnする値は、非nil値に評価された条件の値そのものです。

すべてのconditionsnilになった場合、or式はnilをreturnします。conditionsのない単独の(or)は、nilをreturnします。なぜなら、すべてのconditionsnilになるので(考えてみてください。そうでないのはどれですか?)、これは適切です。

たとえば、この式はxnilまたは整数0かどうかをテストします:

(or (eq x nil) (eq x 0))

and構成と同様に、orcondに置き換えて記述することができます。たとえば:

(or arg1 arg2 arg3)
≡
(cond (arg1)
      (arg2)
      (arg3))

ほとんどの場合、orifに置き換えて記述できますが、完全ではありません:

(if arg1 arg1
  (if arg2 arg2
    arg3))

これは完全に同一ではありません。なぜならarg1またはarg2を2回評価するかもしれないからです。対照的に、(or arg1 arg2 arg3)は2回以上引数を評価することは、決してありません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.4 Iteration

繰り返し(iteration)とは、プログラムの一部を繰り返し実行することを意味します。たとえば、リストの各要素、または0からnの整数にたいして、1度ずつ繰り返し何らかの計算をおこないたいとしましょうEmacs Lispでは、スペシャルフォームwhileでこれを行なうことができます:

Special Form: while condition forms…

whileは、最初にconditionを評価します。結果が非nilの場合は、formsをテキスト順に評価します。その後conditionを再評価して、結果が非nilの場合、再度formsを評価します。この処理は、conditionnilに評価されるまで繰り返されます。

繰り返し回数に制限はありません。このループは、conditionnilに評価されるか、エラーとなるか、throwで抜け出す(Nonlocal Exitsを参照してください)まで計測されるでしょう

whileフォームの値は、常にnilです。

(setq num 0)
     ⇒ 0
(while (< num 4)
  (princ (format "Iteration %d." num))
  (setq num (1+ num)))
     -| Iteration 0.
     -| Iteration 1.
     -| Iteration 2.
     -| Iteration 3.
     ⇒ nil

各繰り返しごとに何かを実行して、その後も終了テストを行なう“repeat...until”ループを記述するには、以下のようにwhileの1番目の引数として、bodyの後に終了テストを記述して、それをprognの中に配します:

(while (progn
         (forward-line 1)
         (not (looking-at "^$"))))

これは1行前方に移動して、空行に達するまで行単位の移動を継続します。独特なのは、whileがbodyをもたず、終了テスト(これはポイント移動の実処理も行ないます)だけという点です。

マクロdolistおよびdotimesは、2つの一般的な種類のループを記述する、便利な方法を提供します。

Macro: dolist (var list [result]) body…

この構成は、listの各要素にたいして1度bodyを実行し、カレント要素をローカルに保持するように、変数varにバインドします。その後、resultを評価した値、またはresultが省略された場合はnilをreturnします。たとえば、以下はreverse関数を定義するために、dolistを使用する方法の例です:

(defun reverse (list)
  (let (value)
    (dolist (elt list value)
      (setq value (cons elt value)))))
Macro: dotimes (var count [result]) body…

この構成は、0以上count未満の各整数にたいして1度bodyを実行し、その繰り返しでの整数を、変数varにバインドします。その後、resultの値、またはresultが省略された場合はnilをreturnします。以下は、dotimesを使用して、何らかの処理を100回行なう例です:

(dotimes (i 100)
  (insert "I will not obey absurd orders\n"))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5 Nonlocal Exits

非ローカル脱出(nonlocal exit)とは、プログラム内のある位置から、別の離れた位置へ、制御を移します。Emacs Lispでは、エラーの結果として非ローカル脱出が発生することがあります。明示的な制御の下で非ローカル脱出を使用することもできます。非ローカル脱出は、脱出しようとしている構成により作成された、すべての変数バインディングのバインドを外します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.1 Explicit Nonlocal Exits: catch and throw

ほとんどの制御構造は、そのコンストラクト自身内部の制御フローだけに影響します。関数throwは、通常のプログラム実行でのこのルールの例外です。これは、リクエストにより非ローカル脱出を行ないます(他にも例外はありますが、それらはエラー処理だけのものです)。throwcatchの内部で試用され、catchに制御を戻します。たとえば:

(defun foo-outer ()
  (catch 'foo
    (foo-inner)))

(defun foo-inner ()
  …
  (if x
      (throw 'foo t))
  …)

throwフォームが実行された場合は、対応するcatchに制御を移し、catchは即座にreturnします。throwの後のコードは実行されません。throwの2番目の引数は、catchのreturn値として使用されます。

関数throwは、1番目の引数にもとづいて、それにマッチするcatchを探します。throwは、1番目の引数が、throwで指定されたものとeqcatchを検索します。複数の該当するcatchがある場合、最内のものが優先されます。したがって、上記の例ではthrowfooを指定し、foo-outer内のcatchが同じシンボルを指定しているので、(この間に他のマッチするcatchは存在しないと仮定すると)catchが該当します。

throwの実行により、マッチするcatchまでのすべてのリスプ構成(関数呼び出しを含む)を脱出します。この方法によりletや関数呼び出しのようなバインディング構成を脱出する場合、これらの構成を正常にexitしたときのように、そのバインディングは解かれます(Local Variablesを参照してください)。同様にthrowは、save-excursion(Excursionsを参照してください)により保存されたバッファーと位置を復元します。throwが、スペシャルフォームunwind-protectを脱出した場合、unwind-protectにより設定されたいくつかのクリーンアップも実行します。

ジャンプ先となるcatch内にレキシカル(局所的)である必要はありません。throwは、catch内で呼び出された別の関数から、同じようにに呼び出すことができます。throwが行なわれたのが、順序的に、catchに入った後でexitする前である限り、そのthrowcatchにアクセスできます。エディターのコマンドループから戻るexit-recursive-editのようなコマンドで、throwが使用されるのは、これが理由です。

Common Lispに関する注意: Common Lispを含む、他のほとんどのバージョンのLispは、非シーケンシャルに制御を移す、いくつかの方法 — たとえばreturnreturn-fromgo — をもちます。Emacs Lispの場合は、throwだけです。cl-libライブラリーは、これらのうちいくつかを提供します。Blocks and Exits in Common Lisp Extensionsを参照してください。

Special Form: catch tag body…

catchは、throw関数にたいするreturn位置を確立します。return位置はtagにより、そのような他のreturn位置と区別されます。tagは、nil以外の任意のLispオブジェクトです。引数tagはreturn位置が確立される前に、通常どおり評価されます。

return位置が効果をもつことにより、catchbodyのフォームをテキスト順に評価します。フォームが(エラーは非ローカル脱出なしで)通常に実行された場合、bodyの最後のフォームの値が、catchからreturnされます。

bodyの実効の間にthrowが実行された場合、tagと同じ値を指定すると、catchフォームは即座にexitします。returnされる値は、それが何であれ、throwの2番目の引数に指定された値です。

Function: throw tag value

throwの目的は、以前にcatchにより確立されたreturn位置に戻ることです。引数tagは、既存のさまざまなreturn位置からrturn位置を選択するために使用されます。複数のreturn位置がtagにマッチする場合、最内のものが使用されます。

引数valueは、catchからreturnされる値として使用されます。

タグtagのreturn位置が存在しない場合、データ(tag value)とともに、no-catchエラーがシグナルされます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.2 Examples of catch and throw

2重にネストされたループから脱出する1つの方法は、catchthrowを使うことです(ほとんどの言語では、これは“goto”により行なわれるでしょう)。ここでは、ijを、0から9に変化させて(foo i j)を計算します:

(defun search-foo ()
  (catch 'loop
    (let ((i 0))
      (while (< i 10)
        (let ((j 0))
          (while (< j 10)
            (if (foo i j)
                (throw 'loop (list i j)))
            (setq j (1+ j))))
        (setq i (1+ i))))))

fooが非nilをreturnした場合、即座に処理を止めて、ijのリストをreturnしています。fooが常にnilをreturnする場合、catchは通常どおりreturnし、その値はwhileの結果であるnilとなります。

以下では、2つのreturn位置を1度に表す、微妙に異なるトリッキーな例を2つ示します。最初に、同じタグhackにたいする2つのreturn位置があります:

(defun catch2 (tag)
  (catch tag
    (throw 'hack 'yes)))
⇒ catch2

(catch 'hack
  (print (catch2 'hack))
  'no)
-| yes
⇒ no

どちらのreturn位置もthrowにマッチするタグをもつので、内側のもの、つまりcatch2で確立されたものにgotoします。したがってcatch2は通常どおり値yesをreturnするので、その値がプリントされます。最後に外側のcatchの2番目のbody、つまり'noが評価されて、外側のcatchからそれがreturnされます。

ここで、catch2に与える引数を変更してみます:

(catch 'hack
  (print (catch2 'quux))
  'no)
⇒ yes

この場合も2つのreturn位置がありますが、今回は外側だけがタグhackをもち、内側のものは、かわりにタグquuxをもちます。したがって、throwにより、外側のcatchが値yesをreturnします。関数printが呼び出されることはなく、bodyのフォーム'noも決して評価されません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.3 Errors

Emacs Lispが、何らかの理由により評価できないようなフォームの評価を試みた場合には、エラー(error)シグナル(signal)されます。

エラーがシグナルされた場合、エラーメッセージの表示とカレントこまんどの実行の終了が、Emacsデフォルトの反応です。たとえばバッファーの最後でC-fとタイプしたときのように、ほとんどの場合、これは正しい反応です。

複雑なプログラムでは、単なる終了が望ましくない場合もあるでしょう。たとえば、そのプログラムはデータ構造に一時的に変更を行なっていたり、プログラム終了前に削除すべき一時バッファーを作成しているかもしれません。このような場合、エラー時に評価されるクリーンアップ式(cleanup expressions)を設定するために、unwind-protectを使用するでしょう(Cleaning Up from Nonlocal Exitsを参照してください)。サブルーチン内のエラーにもかかわらずに、プログラムの実行を継続したいときがあるかもしれません。この場合、エラー時のリカバリーを制御するためのエラーハンドラー(error handlers)を設定するために、condition-caseを使用するでしょう。

エラーハンドリングを使用せずに、プログラムの一部から別の部分へ制御を移すためには、catchthrowを使用します。Explicit Nonlocal Exits: catch and throwを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.3.1 How to Signal an Error

エラーのシグナリング(signaling)とは、エラーの処理を開始することを意味します。エラー処理は通常、実行中のプログラムのすべて、または一部をアボート(abort)して、エラーをハンドルするためにセットアップされた位置にreturnします。ここでは、エラーをシグナルする方法を記述します。

ほとんどのエラーは、たとえば、整数にたいしてCARを求めたり、バッファーの最後で1文字前方に移動したときなどのように、他の目的のために呼び出したLisp基本関数の中で、“自動的”にシグナルされます。関数errorsignalで、明示的にエラーをシグナルすることもできます。

ユーザーがC-gをタイプしたときに発生するquitは、エラーとは判断されませんが、ほとんどはエラーと同様に扱われます。Quittingを参照してください。

すべてのエラーメッセージはそれぞれ、何らかのエラーメッセージを指定します。そのメッセージは、何が悪いのか(“File does not exist”)、物事がどうしてそうあるべきではない(“File must exist”)かを示すべきです。Emacs Lispの監修では、エラーメッセージは大文字で開始され、句読点で終わるべきではありません。

Function: error format-string &rest args

この関数は、format-stringargsにたいして、format(Formatting Stringsを参照してください)を適用することにより構築されたエラーメッセージとともに、エラーをシグナルします。

以下は、errorを使用する典型的な例です:

(error "That is an error -- try something else")
     error→ That is an error -- try something else

(error "You have committed %d errors" 10)
     error→ You have committed 10 errors

2つの引数 — エラーシンボルerrorと、formatによりreturnされる文字列を含むリスト — でsignalを呼び出すことにより、errorは機能します。

警告: エラーメッセージとして固定の文字列を使用したい場合、単に(error string)とは記述しないでください。もしstringが‘%’を含む場合、それはフォーマット指定子(format specifier)として解釈されてしまうので、望む結果は得られません。かわりに、(error "%s" string)を使用してください。

Function: signal error-symbol data

この関数は、error-symbolにより命名されるエラーをシグナルします。引数dataは、エラーの状況に関連する追加のLispオブジェクトのリストです。

引数error-symbolは、エラーシンボル(error symbol)define-errorにより定義されYたシンボル — でなければなりません。これはEmacs Lispが異なる種類のエラーをクラス分けする方法です。エラーシンボル(error symbol)、エラーコンディション(error condition)、コンディション名(condition name)の説明については、Error Symbols and Condition Namesを参照してください。

エラーが処理されない場合、エラーメッセージをプリントするために2つの引数が使用されます。このエラーメッセージは通常、error-symbolerror-messageプロパティーにより提供されます。dataが非nilの場合、その後にコロンと、dataの評価されていない要素を、カンマで区切ったリストが続きます。errorが発生した場合、エラーメッセージは、dataCAR(文字列でなければなりません)です。file-errorのサブカテゴリーは、特別に処理されます。

data内のオブジェクトの数と重要性は、error-symbolに依存します。たとえば、wrong-type-argumentエラーでは、リスト内には2つのオブジェクト — 期待する型を記述する述語と、その型への適合に失敗したオブジェクト — であるべきです。

エラーを処理する任意のエラーハンドラーにたいして、error-symboldataの両方を利用できます。condition-caseは、ローカル変数を(error-symbol . data)というフォームでバインドします(Writing Code to Handle Errorsを参照してください)。

関数signalは、決してreturnしません。

(signal 'wrong-number-of-arguments '(x y))
     error→ Wrong number of arguments: x, y

(signal 'no-such-error '("My unknown error condition"))
     error→ peculiar error: "My unknown error condition"
Function: user-error format-string &rest args

この関数は、errorとまったく同じように振る舞いますが、errorではなく、user-errorというエラーシンボルを使用します。名前が示唆するように、このエラーはコード自身のエラーではなく、ユーザーパートのエラーの報告を意図しています。たとえば、Infoの閲覧履歴の開始を超えて履歴を遡るためにコマンドInfo-history-back (l)を使用した場合、Emacsはuser-errorをシグナルします。このようなエラーでは、たとえdebug-on-errorが非nilであっても、デバッガーへのエントリーは発生しません。Entering the Debugger on an Errorを参照してください。

Common Lispに関する注意: Emacs Lispには、Common Lispのような継続可能なエラーのような概念は存在しません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.3.2 How Emacs Processes Errors

エラーがシグナルされたとき、signalは、そのエラーにたいするアクティブなハンドラー(handler)を検索します。ハンドラーとは、Lispプログラムの一部でエラーが発生したときに実行するよう意図された、Lisp式のシーケンスです。そのエラーが適切なハンドラーをもつ場合、そのハンドラーが実行され、そのハンドラーの後から実行が再開されます。ハンドラーは、そのハンドラーが設定されたcondition-caseの環境内で実行されます。condition-case内のすべての関数呼び出しはすでに終了しているので、ハンドラーがそれらにreturnすることはありません。

そのエラーにたいする適切なハンドラーが存在しない場合は、カレントコマンドを終了して、エディターのコマンドループに制御をreturnします(コマンドループは、すべての種類のエラーにたいする暗黙のハンドラーをもちます)。コマンドループのハンドラーは、エラーメッセージをプリントするために、エラーシンボルと、関連付けられたデータを使用します。変数command-error-functionを使用して、これが行なわれる方法を制御できます:

Variable: command-error-function

この変数は、もし非nilの場合はEmacsのコマンドループに制御をreturnしたエラーの処理に使用する関数を指定します。この関数は3つの引数をとります。1つ目はdataで、condition-caseが自身の変数にバインドするのと同じフォームです。2つ目はcontextで、これはエラーが発生した状況を記述する文字列、またはnil(よくある)です。3つ目はcallerで、これはエラーをシグナルした基本関数を呼び出したLisp関数です。

明示的なハンドラーのないエラーは、Lispデバッガーを呼び出すかもしれません。変数debug-on-error (Entering the Debugger on an Errorを参照してください)が非nilの場合、デバッガーが有効です。エラーハンドラーとは異なり、デバッガーはそのエラーの環境内で実行されるので、エラー時の変数の値を正確に調べることができます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.3.3 Writing Code to Handle Errors

エラーをシグナルすることによる通常の効果は、実行されていたコマンドを終了して、Emacsエディターのコマンドループに即座にreturnすることです。スペシャルフォームcondition-caseを使用して、エラーハンドラーを設定することにより、プログラム内の一部で発生するエラーのをトラップを調整することができます。以下は単純な例です:

(condition-case nil
    (delete-file filename)
  (error nil))

これは、filenameという名前のファイルを削除して、任意のエラーをcatchして、エラーが発生した場合はnilを参照してください(このような単純なケースでは、マクロignore-errorsを使用することもできます。以下を参照してください)。

condition-case構成は、insert-file-contents呼び出しでのファイルオープンの失敗のような、予想できるエラーをトラップするために多用されます。condition-case構成は、ユーザーからの読み取った式を評価するプログラムのような、完全に予測できないエラーのトラップにも使用されます。

condition-caseの2番目の引数は、保護されたフォーム(protected form)と呼ばれます(上記の例では、保護されたフォームは、delete-fileの呼び出しです)。このフォームの実行が開始されると、エラーハンドラーは効果をもち、このフォームがreturnすると不活性になります。その間のすべてにおいて、エラーハンドラーは効果をもちます。特に、このフォームで呼び出された関数、およびそのサブルーチンなどを実行する間、エラーハンドラーは効果をもちます。厳密にいうと、保護されたフォーム自身ではなく、保護されたフォームにより呼び出されたLisp基本関数(signalerrorを含む)だけがシグナルされるというのは、よいことです。

保護されたフォームの後の引数はハンドラーです。各ハンドラーは、どのエラーを処理するかを指定する、1つ以上のコンディション名(condition names)(シンボル)をリストします。エラーがシグナルされたとき、エラーシンボルはコンディション名のリストも定義します。エラーが共通の条件名をもつ場合、そのハンドラーはそのエラーに適用されます。上記の例では、1つのハンドラーがあり、それはすべてのエラーをカバーする条件名errorを指定しています。

適切なハンドラーの検索は、もっとも最近に設定されたハンドラーから開始して、設定されたすべてのハンドラーをチェックします。したがって、ネストされたcondition-caseフォームに同じエラー処理がある場合、内側のハンドラーがそれを処理します。

何らかのcondition-caseによりエラーが処理された場合、debug-on-errorでエラーによりデバッガーが呼び出されるようにしていても、通常はデバッガーの実行が抑制されます。

condition-caseにより補足されるようなエラーをデバッグできるようにしたい場合は、変数debug-on-signalに非nil値をセットします。以下のようにコンディションの中にdebugを記述することにより、最初にデバッガーを実行するような、特定のハンドラーを指定することもできます:

(condition-case nil
    (delete-file filename)
  ((debug error) nil))

ここでのdebugの効果は、デバッガー呼び出しを抑制するcondition-caseを防ぐことだけです。debug-on-errorおよびその他のフィルタリングメカニズムがデバッガーを呼び出すように指定されているときだけ、エラーによりデバッガーが呼び出されます。Entering the Debugger on an Errorを参照してください。

Macro: condition-case-unless-debug var protected-form handlers…

マクロcondition-case-unless-debugは、そのようなフォームのデバッギングを処理する、別の方法を提供します。このマクロは、変数debug-on-errornilの場合、つまり任意のエラーを処理しないようなケース以外は、condition-caseとまったく同様に振る舞います。

特定のハンドラーがそのエラーを処理するとEmacsが判断すると、Emacsは制御をそのハンドラーにreturnします。これを行うために、Emacsはそのとき脱出しつつあるバインディング構成により作成されたすべての変数のバインドを解き、そのとき脱出しつつあるすべてのunwind-protectフォームを実行します。制御がそのハンドラーに達すると、そのハンドラーのbodyが通常どおり実行されます。

そのハンドラーのbodyを実行した後、condition-caseフォームから実行がreturnされます。保護されたフォームは、そのハンドラーの実行の前に完全にexitしているので、そのハンドラーはそのエラーの位置から実行を再開することはできず、その保護されたフォーム内で作られた変数のバインディングを調べることもできません。ハンドラーが行なえることは、クリーンアップと、処理を進行させることだけです。

エラーのシグナルとハンドルには、throwcatch(Explicit Nonlocal Exits: catch and throw)に類似する点がいくつかありますが、これらは完全に別の機能です。エラーはcatchでキャッチできず、throwをエラーハンドラーで処理することはできません(しかし対応するcatchが存在しないときにthrowを仕様することによりシグナルされるエラーは、処理できます)。

Special Form: condition-case var protected-form handlers…

このスペシャルフォームは、protected-formの実行を囲い込むエラーハンドラーhandlersを確立します。エラーなしでprotected-formが実行された場合、returnされる値はcondition-caseフォームの値になります。この場合、condition-caseは効果をもちません。protected-formの間にエラーが発生した場合、condition-caseは違いをもちます。

それぞれのhandlersは、(conditions body…)というフォームのリストです。ここでconditionsは、ハンドルされるエラーコンディション名、またはそのハンドラーの前にデバッガーを実行するためのコンディション名(debugを含みます)です。bodyは、このハンドラーがエラーを処理するときに実行される、1つ以上のLisp式です。

(error nil)

(arith-error (message "Division by zero"))

((arith-error file-error)
 (message
  "Either division by zero or failure to open a file"))

発生するエラーはそれぞれ、それが何の種類のエラーかを記述するエラーシンボル(error symbol)をもち、これはコンディション名のリストも記述します(Error Symbols and Condition Namesを参照してください)。Emacsは、1つ以上のコンディション名を指定するハンドラーにたいして、すべてのアクティブなcondition-caseフォームを検索します。condition-caseの最内のマッチは、そのエラーを処理します。このcondition-caseでは、最初に適合したハンドラーが、そのエラーを処理します。

ハンドラーのbodyを実行した後、condition-caseは通常どおりreturnし、ハンドラーのbodyの最後の値を、ハンドラー全体の値として使用します。

引数varは変数です。protected-formを実行するとき、condition-caseはこの変数をバインドせず、エラーを処理するときだけバインドします。その場合は、varエラー記述(error description)にバインドします。これはエラーの詳細を与えるリストです。このエラー記述は、(error-symbol . data)というフォームをもちます。ハンドラーは、何を行なうか決定するために、このリストを参照することができます。たとえば、ファイルオープンの失敗にたいするエラーの場合、ファイル名がdata(エラー記述の3番目の要素)の2番目の要素になります。

varnilの場合、それはバインドされた変数がないことを意味します。この場合、エラーシンボルおよび関連するデータは、そのハンドラーでは利用できません。

より外側のレベルのハンドラーにcatchさせるために、condition-caseによりcatchされたシグナルを再度throwする必要がある場合もあります。以下はこれを行なう方法です:

  (signal (car err) (cdr err))

ここでerrはエラー記述変数(error description variable)で、condition-caseの1番目の引数は、再throwしたいエラーコンディションです。Definition of signalを参照してください。

Function: error-message-string error-descriptor

この関数は、与えられたエラー記述子(error descriptor)にたいするエラーメッセージ文字列をreturnします。これは、そのエラーにたいする通常のエラーメッセージをプリントすることにより、エラーを処理したい場合に有用です。Definition of signalを参照してください。

以下は、0除算の結果によるエラーを処理するために、condition-caseを使用する例です。このハンドラーは、(beepなしで)エラーメッセージを表示して、非常に大きい数をreturnします。

(defun safe-divide (dividend divisor)
  (condition-case err
      ;; 保護されたフォーム。
      (/ dividend divisor)
    ;; ハンドラー。
    (arith-error                        ; Condition.
     ;; このエラーにたいする、通常のメッセージを表示する。
     (message "%s" (error-message-string err))
     1000000)))
⇒ safe-divide

(safe-divide 5 0)
     -| Arithmetic error: (arith-error)
⇒ 1000000

このハンドラーはコンディション名arith-errorを指定するので、division-by-zero(0除算)エラーだけを処理します。他の種類のエラーは(このcondition-caseによっては)、処理されません。したがって:

(safe-divide nil 3)
     error→ Wrong type argument: number-or-marker-p, nil

以下は、errorによるエラーを含む、すべての種類のエラーをcatchするcondition-caseです:

(setq baz 34)
     ⇒ 34

(condition-case err
    (if (eq baz 35)
        t
      ;; 関数errorの呼び出し
      (error "Rats!  The variable %s was %s, not 35" 'baz baz))
  ;; フォームではないハンドラー。
  (error (princ (format "The error was: %s" err))
         2))
-| The error was: (error "Rats!  The variable baz was 34, not 35")
⇒ 2
Macro: ignore-errors body…

これは、その実行中に発生する任意のエラーを無視して、bodyの実行を構築します。その実行にエラーがなかった場合、ignore-errorsbody内の最後のフォームの値をreturnし、それ以外はnilをreturnします。

以下は、このセクションの最初の例を、ignore-errorsを使用して記述する例です:

  (ignore-errors
   (delete-file filename))
Macro: with-demoted-errors format body…

このマクロは、いわばignore-errorsの穏やかなバージョンです。これはエラーを完全に抑止するのではなく、エラーをメッセージに変換します。これはメッセージのフォーマットに、文字列formatを使用します。formatは、"Error: %S"のように、単一の‘%’シーケンスを含むべきです。エラーをシグナルすると予測されないが、もし発生した場合は堅牢であるべきようなコードの周囲に、with-demoted-errorsを使用します。このマクロは、condition-caseではなく、condition-case-unless-debugを使用することに注意してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.3.4 Error Symbols and Condition Names

エラーをシグナルするとき、想定するエラーの種類を指定するために、エラーシンボル(error symbol)を指定します。エラーはそれぞれ、それをカテゴリー分けするために、ただ1つのエラーシンボルをもちます。これはEmacs Lisp言語で定義されるエラーの、もっとも良い分類方法です。

これら狭義の分類は、エラー条件(error conditions)と呼ばれる、より広義のクラス階層にグループ化され、それらはコンディション名(condition names)により識別されます。そのようなもっとも狭義なクラスは、エラーシンボル自体に属します。つまり各エラーシンボルは、コンディション名でもあるのです。すべての種類のエラー(quitを除く)を引き受けるコンディション名errorに至る、より広義のクラスにたいするコンディション名も存在します。したがって、各エラーは1つ以上のコンディション名をもちます。つまり、errorerrorとは区別されるエラーシンボル、もしかしたらその中間に分類されるものかもしれません。

Function: define-error name message &optional parent

シンボルをエラーシンボルとするために、シンボルは親コンディションをとるdefine-errorで定義されなければなりません。この親は、この種のエラーが属するコンディションを定義します。親の推移的な集合は、常にそのエラーシンボルと、シンボルerrorを含みます。quitはエラーと判断されないので、quitの親の集合は、単なる(quit)です。

親のコンディションに加えて、エラーシンボルはメッセージ(message)をもち、これは処理されないエラーがシグナルされたときプリントされる文字列です。そのメッセージが有効でない場合、エラーメッセージ‘peculiar error’が使用されます。Definition of signalを参照してください。

内部的には、親の集合はエラーシンボルのerror-conditionsプロパティーに格納され、メッセージはエラーシンボルのerror-messageプロパティーに格納されます。

以下は、新しいエラーシンボルnew-errorを定義する例です:

(define-error 'new-error "A new error" 'my-own-errors)

このエラーは複数のコンディション名 — もっとも狭義の分類new-error、より広義の分類を想定するmy-own-errors、およびmy-own-errorsのコンディションすべてを含むerrorで、これはすべての中でもっとも広義なものです。

エラー文字列は大文字で開始されるべきですが、ピリオドで終了すべきではありません。これはEmacsの他の部分との整合性のためです。

もちろんEmacs自身がnew-errorをシグナルすることはありません。あなたのコード内で明示的にsignal(Definition of signalを参照してください)を呼び出すことにより、これを行なうことができるのです。

(signal 'new-error '(x y))
     error→ A new error: x, y

このエラーは、エラーの任意のコンディション名により処理することができます。以下の例は、new-errorとクラスmy-own-errors内の他の任意のエラーを処理します:

(condition-case foo
    (bar nil t)
  (my-own-errors nil))

エラーが分類される有効な方法は、コンディション名による方法で、その名前はハンドラーのエラーのマッチに使用されます。エラーシンボルは、意図されたエラーメッセージと、コンディション名のリストを指定する便利な方法であるという役割だけです。1つのエラーシンボルではなく、コンディション名のリストをsignalに与えるのは、面倒でしょう。

対照的に、コンディション名を伴わずにエラーシンボルだけを使用した場合、それはcondition-caseの効果を著しく減少させるでしょう。コンディション名は、エラーハンドラーを記述するとき、一般性のさまざまなレベルにおいて、エラーをカテゴリー分けすることを可能にします。エラーシンボルを単独で使用することは、もっとも狭義なレベルの分類を除くすべてを捨てることです。

主要なエラーシンボルと、それらのコンディションについては、Standard Errorsを参照してください。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.4 Cleaning Up from Nonlocal Exits

unwind-protect構成は、データ構造を一時的に不整合な状態に置くときは、重要です。これはエラーやthrouのイベントにより、再びデータを整合された状態にすることができます(バッファー内容の変更だけに使用される、他のクリーンアップ構成は、アトミックな変更グループです。Atomic Change Groupsを参照してください)。

Special Form: unwind-protect body-form cleanup-forms…

unwind-protectは、制御がbody-formを離れる場合に、cleanup-formsが評価されるという保証の下、なにが起こった可に関わらず、body-formを実行します。body-formは通常どおり完了するかもしれず、unwind-protectの外でthrowが実行されたり、エラーが発生するかもしれませんが、cleanup-formsは評価されます。

body-formが正常に終了した場合、unwind-protectcleanup-formsを評価した後で、body-formの値をreturnします。body-formが終了しなかった場合、unwind-protectは通常の意味における値は、returnしません。

unwind-protectにより保護されるのは、body-formだけです。cleanup-forms自体の任意のフォームが、(throwまたはエラーにより)非ローカルにexitした場合、unwind-protectは残りのフォームが評価されることを保証しませんcleanup-formsの中の1つが失敗することが問題となる場合は、そのフォームの周囲に他のunwind-protectを配して保護します。

現在アクティブなunwind-protectフォーム数と、ローカルの変数バインディング数の和は、max-specpdl-size(Local Variablesを参照してください)により制限されます。

たとえば、以下は一時的な使用のために不可視のバッファーを作成して、終了する前に確実にそのバッファーをkillする例です:

(let ((buffer (get-buffer-create " *temp*")))
  (with-current-buffer buffer
    (unwind-protect
        body-form
      (kill-buffer buffer))))

(kill-buffer (current-buffer))のように記述して、変数bufferを使用せずに、同様のことを行えると思うかもしれません。しかし上の例は、別のバッファーにスイッチしたときにbody-formでエラーが発生した場合、より安全なのです(一時的なバッファーをkillするとき、そのバッファーがカレントとなることを確実にするために、かわりにbody-formの周囲にsave-current-bufferを記述することもできます)。

Emacsには、上のコードとおおよそ等しいコードに展開される、with-temp-bufferという標準マクロが含まれます(Current Bufferを参照してください)。このマニュアル中で定義されるいくつかのマクロは、この方法でunwind-protectを使用します。

以下は、FTPパッケージ由来の、実際の例です。これは、リモートマシンへの接続の確立を試みるために、プロセス(Processesを参照してください)を作成します。関数ftp-loginは、関数のライター(writer)が予想できないことによる多くの問題から非常に影響を受けるので、失敗イベントでプロセスの削除を保証するフォームで保護されています。そうしないと、Emacsは無用なサブプロセスで一杯になってしまうでしょう。

(let ((win nil))
  (unwind-protect
      (progn
        (setq process (ftp-setup-buffer host file))
        (if (setq win (ftp-login process host user password))
            (message "Logged in")
          (error "Ftp login failed")))
    (or win (and process (delete-process process)))))

この例には小さなバグがあります。ユーザーがquitするためにC-gとタイプした場合、関数ftp-setup-bufferがreturnした後、即座にquitが発生しますが、それは変数processがセットされる前なので、そのプロセスはkillされないでしょう。このバグを簡単に訂正する方法はありませんが、少なくともこれは非常に稀なことだと言えます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11 Variables

変数(variable)とは、プログラム内で値を表すために使用される名前です。Lispでは、変数はそれぞれLispシンボルとして表されます(Symbolsを参照してください)。変数名は単にそのシンボルの名前であり、変数の値はそのシンボルの値セル(value cell)に格納されます6Symbol Componentsを参照してください。Emacs Lispでは、シンボルを変数として使用することは、同じシンボルを関数名として使用することと関係ありません。

このマニュアル中で前に記したとおり、Lispプログラムはまず第1にLispオブジェクトとして表され、副次的にテキストとして表現されます。Lispプログラムのテキスト的な形式は、そのプログラムを構成するLispオブジェクトの入力構文により与えられます。したがって、Lispプログラム内の変数のテキスト的な形式は、その変数を表すシンボルの入力構文を使用して記述されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1 Global Variables

変数を使用するための一番シンプルな方法は、グローバル(globally)に使用する方法です。これは、ある時点でその変数はただ1つの値をもち、その値が(少なくともその時点では)Lispシステム全体で効果をもつことを意味します。あらたな値を指定するまで、その値が効果をもちます。新しい値で古い値を置き換えるとき、古い値を追跡する情報は変数内に残りません。

シンボルの値はsetqで指定します。たとえば、

(setq x '(a b))

これは、変数xに値(a b)を与えます。setqはスペシャルフォームであることに注意してください。これは1番目の引数(変数の名前)は評価しませんが、2番目の引数(新しい値)は評価します。

変数が1度値をもつと、そのシンボル自身を式として使用することにより、参照することができます。したがって、

x ⇒ (a b)

これは上記のsetqフォームが実行された場合です。

同じ変数を再びセットした場合、新しい値は古い値を置き換えます:

x
     ⇒ (a b)
(setq x 4)
     ⇒ 4
x
     ⇒ 4

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2 Variables that Never Change

Emacs Lispでは、特定のシンボルは、通常は自分自身に評価されます。これらのシンボルにはnilt、同様に名前が‘:’で始まる任意のシンボル(これらはキーワードと呼ばれます)が含まれます。これらのシンボルは、リバインドや、値の変更はできません。niltへのセットやリバインドは、setting-constantエラーをシグナルします。これはキーワード(名前が‘:’で始まるシンボル)についても当てはまります。ただしキーワードが標準のobarrayにinternされている場合、そのようなシンボルを自分自身にセットしてもエラーになりません。

nil ≡ 'nil
     ⇒ nil
(setq nil 500)
error→ Attempt to set constant symbol: nil
Function: keywordp object

この関数は、objectが‘:’で始まる名前のシンボルで、標準のobarrayにinternされているの場合はt、それ以外はnilをreturnします。

これらの定数はスペシャルフォームdefconst(Defining Global Variablesを参照してください)を使用して定義された“定数(constant)”とは、根本的に異なります。defconstフォームは、人間の読み手に値の変更を意図しない変数であることを知らせる役目は果たしますが、実際にそれを変更しても、Emacsはエラーを起こしません。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3 Local Variables

グローバル変数は、新しい値で明示的に置き換えるまで値が持続します。変数にローカル値(local value) — Lispプログラム内の特定の部分で効果をもつを与えると便利なときがあります。変数がローカル値をもつとき、わたしたちは変数がその値にローカルにバインド(locally bound)と言い、その変数をローカル変数(local variable)と呼びます。

たとえば、関数が呼び出されるとき、関数の引数となる変数はローカル値(その関数の呼び出しにおいて実際の引数に与えられた値)を受け取ります。これらのローカルバインディングは、その関数のbody内で効果をもちます。他にも、たとえばスペシャルフォームletは特定の変数にたいして明示的にローカルなバインディングを確立し、これはletフォームのbody内で効果を持ちます。

これにたいしてグローバルなバインディング(global binding)とは、(概念的には)グローバルな値が保持される場所です。

ローカルバインディングを確立すると、その変数の以前の値は他の場所に保存されます(または失われます)。わたしたちはこれを、以前の値がシャドーされた(shadowed)と言います。シャドーはグローバル変数とローカル変数の両方で発生し得ます。ローカルバインディングが効果を持つとき、ローカル変数にsetqを使用することにより、ローカルバインディングに指定された値を格納します。ローカルバインディングが効果を持たなくなったとき、以前にシャドーされた値が復元されます(または失われます)。

変数は同時に複数のローカルバインディングを持つことができます(たとえばその変数をバインドするネストされたlet)。カレントバインディング(current binding)とは、実際に効果を持つローカルバインディングのことです。カレントバインディングは、その変数の評価によりreturnされる値を決定し、setqにより影響を受けるバインディングです。

ほとんどの用途において、“最内(innermost)”のローカルバインディング、ローカルバインディングがないときはグローバルバインディングを、カレントバインディングと考えることができます。より正確に言うと、スコープルール(scoping rule)と呼ばれるルールは、プログラム内でローカルバインディングが効果を持つ任意の与えられた場所を決定します。Emacs Lispのスコープルールはダイナミックスコープ(dynamic scoping)と呼ばれ、これは単に実行中のプログラム内の与えられた位置でのカレントバインディングを示し、その変数がまだ存在する場合は、その変数にたいしてもっとも最近作成されたバインディングです。ダイナミックスコープについての詳細と、その代替であるレキシカルスコープ(lexical scoping)と呼ばれるスコープルールについては、Scoping Rules for Variable Bindingsを参照してください。

スペシャルフォームletおよびlet*は、ローカルバインディングを作成するために存在します:

Special Form: let (bindings…) forms…

このスペシャルフォームは、bindingsにより指定される特定の変数セットにたいするローカルバインディングをセットアップしてから、formsのすべてをテキスト順に評価します。これはforms内の最後のフォームの値をreturnします。

bindingsの各バインディングは2つの形式のどちらかです。(i) シンボルの場合。この場合、そのシンボルはnilにローカルにバインドされます。(ii) フォーム(symbol value-form)のリストの場合。この場合symbolvalue-formを評価した結果にローカルにバインドされます。value-formが省略された場合は、nilが使用されます。

bindings内のすべてのvalue-formは、シンボルがそれらにバインドされるに、記述された順番に評価されます。以下は例では、zyの新しい場合(つまり1)にではなく、古い値(つまり2)にバインドされます。

(setq y 2)
     ⇒ 2

(let ((y 1)
      (z y))
  (list y z))
     ⇒ (1 2)
Special Form: let* (bindings…) forms…

このスペシャルフォームはletと似ていますが、次の変数値にたいするローカル値を計算する前に、ローカル値を計算してそれを変数にバインドします。したがて、bindings内の式は、このlet*フォーム内の前のシンボルのバインドを参照できます。以下の例を、上記letの例と比較してください。

(setq y 2)
     ⇒ 2

(let* ((y 1)
       (z y))    ; yの値に今計算されたばかりの値を使用する。
  (list y z))
     ⇒ (1 1)

以下は、ローカルバインディングを作成する、他の機能のリストです:

変数はバッファーローカルなバインディングを持つこともできます(Buffer-Local Variablesを参照してください)。数は多くありませんが、端末ローカル(terminal-local)なバインディングをもつ変数もあります(Multiple Terminalsを参照してください)これらの種類のバインディングは、通常のローカルバインディングのように機能することもありますが、これらはEmacs内の“どこ”であるかに依存してローカライズされます。

User Option: max-specpdl-size

この変数は、ローカルな変数バインディングと、unwind-protectにゆるクリーンアップ(Cleaning Up from Nonlocal Exitsの総数にたいする制限を定義し、この変数を越えるとEmacsはエラー(データに関するエラー"Variable binding depth exceeds max-specpdl-size")をシグナルします。

このリミットは、もし超過したときにエラーが関連付けられている場合には、誤って定義された関数による無限再起を避けるための1つの方法になります。ネストの深さにたいする他の制限としては、max-lisp-eval-depthがあります。Evalを参照してください。

デフォルト値は1300です。Lispデバッガーのエントリーしたとき、もし残りが少ないときは、デバッガーを実行するための空きを作るために、値は増加されます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4 When a Variable is “Void”

シンボルの値セル(Symbol Componentsを参照してください)に値が割り当てられていない場合、その変数はvoid(空)であると言います。

Emacs Lispのデフォルトであるダイナミックスコープルール(see section Scoping Rules for Variable Bindings)の下では、値セルはその変数のカレント値(ローカルまたはグローバル)を保持します。値が割り当てられていない値セルは、値セルにnilをもつのとは異なることに注意してください。シンボルnilはLispオブジェクトであり、他のオブジェクトと同様に変数の値となることができます。nilは値なのです。変数がvoidの場合、その変数の評価を試みると、値をreturnするかわりに、void-variableエラーがシグナルされます。

オプションであるレキシカルスコープルール(lexical scoping rule)の下では、値セル保持できるのは、その変数のグローバル値 — 任意のレキシカルバインディング構造の外側の値だけです。変数がレキシカルにバインドされている場合、ローカル値はそのレキシカル環境により決定されます。したがって、これらのシンボルの値セルに値が割り当てられていなくても、変数はローカル値を持つことができます。

Function: makunbound symbol

この関数は、symbolの値セルを空にして、その変数をvoidにします。この関数はsymbolをreturnします。

symbolがダイナミックなローカルバインディングを持つ場合、makunboundはカレントのバインディングをvoidにし、そのローカルバインディングが効果を持つ限りvoidにします。その後、前にシャドーされたローカル値(またはグローバル値)が再び有効になり、再び有効になった値がvoidでなければ、その変数はvoidでなくなります。

いくつか例を示します(ダイナミックバインディングが有効だとします):

(setq x 1)               ; グローバルバインディングに値をセットする。
     ⇒ 1
(let ((x 2))             ; それをローカルにバインドする。
  (makunbound 'x)        ; ローカルバインディングをvoidにする。
  x)
error→ Symbol's value as variable is void: x
x                        ; グローバルバインディングは変更されない。
     ⇒ 1

(let ((x 2))             ; ローカルにバインドする。
  (let ((x 3))           ; もう1度。
    (makunbound 'x)      ; 最内のローカルバインディングをvoidにする。
    x))                  ; それを参照すると、void。
error→ Symbol's value as variable is void: x

(let ((x 2))
  (let ((x 3))
    (makunbound 'x))     ; 内側のバインディングをvoidにしてから取り除く。
  x)                     ; 外側のletバインディングが有効になる。
     ⇒ 2
Function: boundp variable

この関数はvariable(シンボル)がvoidでなければtをreturnし、voidのときはnilをreturnします。

いくつか例を示します(ダイナミックバインディングが有効だとします):

(boundp 'abracadabra)          ; 最初はvoid。
     ⇒ nil
(let ((abracadabra 5))         ; ローカルにバインドする。
  (boundp 'abracadabra))
     ⇒ t
(boundp 'abracadabra)          ; グローバルではまだvoid。
     ⇒ nil
(setq abracadabra 5)           ; グローバルで非voidにする。
     ⇒ 5
(boundp 'abracadabra)
     ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.5 Defining Global Variables

変数定義(variable definition)とは、そのシンボルをグローバル変数として使用する意図を表明する構成です。これには以下で説明するスペシャルフォームdefvardefconstが使用されます。

変数宣言は3つの目的をもちます。1番目は、コードを読む人にたいして、そのシンボルが特定の方法(変数として)使用されることを意図したものだと知らせることです。2番目は、Lispシステムにたいして、オプションで初期値とドキュメント文字列を与えて、これを知らせることです。3番目は、etagsのようなプログラミングツールにたいして、その変数が定義されている場所を見つけられるように、情報を提供することです。

defconstdefvarの違いは主に、人間の読み手に、値が変更されるかどうかを知らせることにあります。Emacs Lispは実際、defconstで定義された変数の値の変更を妨げません。この2つのフォームの特筆すべき違いは、defconstは無条件で変数を初期化し、defvarは変数が元々voidのときだけ初期化することです。

マスタマイズ可能な変数を定義する場合は、defcustomを使用するべきです(これはサブルーチンとしてdefvarを呼び出します)。Defining Customization Variablesを参照してください。

Special Form: defvar symbol [value [doc-string]]

このスペシャルフォームは、変数としてsymbolを定義します。symbolは評価されないことに注意してください。シンボルはdefvarフォーム内に明示的に表記して定義される必要があります。この変数は特別だとマークされ、これは常にそれがダイナミックにバインドされることを意味します(Scoping Rules for Variable Bindingsを参照してください)。

valueが指定されていてsymbolがvoid(たとえばこのシンボルがダイナミックにバインドされた値を持たないとき。When a Variable is “Void”を参照してください)、valueが評価されて、その結果がsymbolにセットされます。しかしsymbolがvoidでな場合、valueは評価されず、symbolの値は変更されません。valueが省略された場合、いかなる場合もsymbolの値は変更されません。

symbolがカレントバッファー内でバッファーローカルなバインディングをもつ場合、defvarはデフォルト値に作用します。デフォルト値はバッファーローカルなバインディングではなく、バッファーにたいして独立しています。デフォルト値がvoidのときはデフォルト値をセットします。Buffer-Local Variablesを参照してください。

すでにsymbolがレキシカルにバインドされている場合(たとえばレキシカルバインドが有効な状態でletフォーム内にdefvarがあるような場合)、defvarはダイナミックな値をセットします。バインディング構造を抜けるまで、レキシカルバインディングは効果をもちます。Scoping Rules for Variable Bindingsを参照してください。

Emacs Lispモード(eval-defun)でトップレベルのdefvarを評価するとき、eval-defunの特別な機能は、その値がvoidであるかテストすることなく、その変数を無条件にセットします。

引数doc-stringが与えられた場合、それは変数にたいするドキュメント文字列を指定します(そのシンボルのvariable-documentationプロパティーに格納されます)。Documentationを参照してください。

以下にいくつか例を示します。これはfooを定義しますが、初期化は行いません:

(defvar foo)
     ⇒ foo

この例はbarの値を23に初期化して、ドキュメント文字列を与えます:

(defvar bar 23
  "The normal weight of a bar.")
     ⇒ bar

defvarフォームはsymbolをreturnしますが、通常これは値が問題にならないファイル内のトップレベルで使用されます。

Special Form: defconst symbol value [doc-string]

このスペシャルフォームは、ある値としてsymbolを定義して、それを初期化します。これはコードを読む人に、symbolがここで設定される標準的なグローバル値をもち、ユーザーや他のプログラムがそれを変更すべきではないことを知らせます。symbolは評価されないことに注意してください。このシンボルは、defconst内に明示的に記されなければなりません。

defvarと同様、defconstは、変数を特別 — この変数が常にダイナミックにバインドされているという意味 — だとマークします(Scoping Rules for Variable Bindingsを参照してください)。加えて、これはその変数を危険であるとマークします(File Local Variablesを参照してください)。

defconstは常にvalueを評価して、その結果をsymbolの値にセットします。カレントバッファー内でsymbolがバッファーローカルなバインディングをもつ場合、defconstはデフォルト値ではなく、バッファーローカルな値をセットします(しかし、defconstで定義されたシンボルにたいしてバッファーローカルなバインディングを作るべきではありません)。

defconstの使い方の例は、Emacsのfloat-pi — (たとえIndiana State Legislatureが何を試みようと)何者かにより変更されるべきではない、数学定数piにたいする定義です。しかし2番目のdefconstの例のように、これは単にアドバイス的なものです。

(defconst float-pi 3.141592653589793 "The value of Pi.")
     ⇒ float-pi
(setq float-pi 3)
     ⇒ float-pi
float-pi
     ⇒ 3

警告: 変数がローカルバインディングをもつとき(letにより作成された、または関数の引数の場合)に、スペシャルフォームdefconstまたはdefvarを使用すると、これらのフォームはグローバルバインディングではなく、ローカルバインディングをセットします。これは通常、あなたが望むことではないはずです。これを防ぐには、これらのスペシャルフォームをファイル内のトップレベルで使用します。この場所は通常、何のローカルバインディングも効果をもたないので、その変数にたいするローカルバインディングが作成される前にファイルがロードされることが確実だからです。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6 Tips for Defining Variables Robustly

値が関数(または関数のリスト)であるような変数を定義するとき、変数の名前の最後に‘-function’(または‘-functions’)を使います。

他にも、変数名に関する慣習があります。以下はその完全なリストです:

…-hook

変数はノーマルフックです(Hooksを参照してください)。

…-function

値は関数です。

…-functions

値は関数のリストです。

…-form

値はフォーム(式)です。

…-forms

値はフォーム(式)のリストです。

…-predicate

値は述語(predicate) — 1つの引数をとる関数 — で、引数が“正しい(good)”"場合は非nil、“正しくない(bad)”場合はnilをreturnします。

…-flag

nilか、そうでないかだけが意味をもつような値です。そのような変数は結局、やがては多くの値をもつことが多いので、この慣習を強く推奨はしません。

…-program

値はプログラム名です。

…-command

値は完全なシェルコマンドです。

…-switches

値はコマンドにたいして指定するオプションです。

変数を定義するときは、その変数を“安全(safe)”とマークすべきか、それとも“危険(risky)”とマークすべきかを常に考慮してください。File Local Variablesを参照してください。

複雑な値を保持する変数(バインディングをもつkeymapなど)を定義、または初期化するとき、以下のように値の計算をすべてdefvarの中に配置するのが最良です:

(defvar my-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\C-c\C-a" 'my-command)
    …
    map)
  docstring)

この方法にはいくつかの利点があります。1つ目は、ファールをロード中にユーザーが中断した場合、変数はまだ初期化されていないか、初期化されているかのどちらかで、その中間ということはありません。まだ初期化されていない場合、ファイルをリロードすれば正しく初期化されます。2つ目は、1度初期化された変数は、ファイルをリロードしても変更されないことです。コンテンツの一部を変更(たとえばキーのリバインド)するフックをユーザーが実行した場合などに、これは重要です。3つ目は、C-M-xdefvarを評価すると、そのマップは完全に再初期化されることです。

defvarフォーム内に多すぎるコードを配置することには不利な点が1つあります。ドキュメント文字列が変数の名前から離れた場所に配置されることです。これを避ける安全な方法は以下の方法です:

(defvar my-mode-map nil
  docstring)
(unless my-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\C-c\C-a" 'my-command)
    …
    (setq my-mode-map map)))

これは初期化をdefvarの内側に配置した場合とまったく同じ利点をもちますが、変数を再度初期化したい場合は、各フォームにたいして1回ずつ、2度C-M-xをタイプしなければならない点が異なります。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7 Accessing Variable Values

変数を参照する通常の方法は、それに名前をつけるシンボルを記述する方法です。The usual way to reference a variable is to write the symbol which names it. Symbol Formsを参照してください。

時には、実行時にのみ決定される変数を参照したいときがあるかもしれません。そのような場合、プログラム中のテキストで、変数名を指定することはできません。その値を抽出するために、symbol-valueを使うことができます。

Function: symbol-value symbol

この関数は、symbolの値セルに格納された値をreturnします。これには、その変数の(ダイナミックな)カレント値が格納された場所です。その変数がローカルバインディングをもたない場合は、単にその変数のグローバル値になります。変数がvoidの場合、void-variableはエラーをシグナルします。

その変数がレキシカルにバインドされている場合、symbol-valueにより報告される値は、その変数のレキシカル値と同じである必要はありません。レキシカル値はそのシンボルの値セルではなく、レキシカル環境により決定されます。Scoping Rules for Variable Bindingsを参照してください。

(setq abracadabra 5)
     ⇒ 5
(setq foo 9)
     ⇒ 9

;; ここでシンボルabracadabra
;;   値がテストされるシンボル。
(let ((abracadabra 'foo))
  (symbol-value 'abracadabra))
     ⇒ foo

;; ここでは、abracadabraの値、
;;   つまりfooが、
;;   値をテストされるシンボル。
(let ((abracadabra 'foo))
  (symbol-value abracadabra))
     ⇒ 9

(symbol-value 'abracadabra)
     ⇒ 5

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.8 Setting Variable Values

ある変数の値を変更する通常の方法は、スペシャルフォームsetqを使用する方法です。実行時に変数選択を計算する必要がある場合は、関数setを使用します。

Special Form: setq [symbol form]…

このスペシャルフォームは、変数の値を変更するための、もっとも一般的な方法です。symbolにはそれぞれ、新しい値(対応するformが評価された結果)を与えられます。そのシンボルのカレントバインディングは変更されます。

setqsymbolを評価せず、記述されたシンボルをセットします。この引数のことを、自動的にクォートされた(automatically quoted)と呼びます。setqの‘q’は、“quoted(クォートされた)”が由来です。

setqフォームの値は、最後のformの値となります。

(setq x (1+ 2))
     ⇒ 3
x                   ; ここでxはグローバル値をもつ。
     ⇒ 3
(let ((x 5))
  (setq x 6)        ; xのローカルバインディングをセット。
  x)
     ⇒ 6
x                   ; グローバル値は変更されない。
     ⇒ 3

1番目のformが評価されてから1番目のsymbolがセットされ、次に2番目のformが評価されてからsymbolが評価されて、...となることに注意してください:

(setq x 10          ; ここで、xがセットされるのは
      y (1+ x))     ;   yの計算前であることに注目。
     ⇒ 11
Function: set symbol value

この関数は、symbolの値セルにvalueを配置します。これはスペシャルフォームではなく関数なので、シンボルにセットするために、symbolに記述された式は評価されます。return値はvalueです。

ダイナミックな変数バインドが有効な場合(デフォルト)、setは自身の引数symbolを評価しますが、setqは評価しないという点を除き、setsetqと同じ効果をもちます。しかし、変数がレキシカルバインドの場合、setは変数のダイナミックな値に影響し、setqは変数のカレント値(レキシカル値)に影響します。Scoping Rules for Variable Bindingsを参照してください。

(set one 1)
error→ Symbol's value as variable is void: one
(set 'one 1)
     ⇒ 1
(set 'two 'one)
     ⇒ one
(set two 2)         ; twoは、シンボルoneに評価される。
     ⇒ 2
one                 ; したがってoneがセットされる。
     ⇒ 2
(let ((one 1))      ; oneのこのバインディングがセットされるのであって
  (set 'one 3)      ;   グローバル値はセットされない。
  one)
     ⇒ 3
one
     ⇒ 2

symbolが実際のシンボルでない場合、wrong-type-argumentエラーがシグナルされます。

(set '(x y) 'z)
error→ Wrong type argument: symbolp, (x y)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9 Scoping Rules for Variable Bindings

ある変数にたいするローカルバインディングを作成するとき、そのバインディングはプログラムの限られた一部だけに効果をもちます(see section Local Variables)。このセクションでは、これが正確には何を意味するかについて説明します。

ローカルバインディングはそれぞれ、個別にスコープ(scope: 範囲という意味)エクステント(extent: これも範囲を意味する)をもちます。スコープは、そのバインディングにアクセスできるのが、テキストのソースコードのどこ(where)であるかを示します。エクステントは、プログラムの実行中に、そのバインディングが存在するのがいつ(when)であるかを示します。

デフォルトでは、Emacsが作成したローカルバインディングは、ダイナミックバインディング(dynamic binding)です。このようなバインディングは、ダイナミックスコープ(dynamic scope)をもち、それはプログラムの任意の範囲が、その変数バインディングにアクセスするかもしれないことを意味します。これはダイナミックエクステント(dynamic extent)ももちます。これはそのバインディング構造(letフォームのbodyなど)が実行される間だけ、そのバインディングが存続することを意味します。

Emacsはオプションでレキシカルバインディング(lexical binding)を作成することができます。レキシカルバインディングはレキシカルスコープ(lexical scope)をもち、これはその変数にたいする任意の参照が、バインディング構造内にテキスト的に配置されなければならないことを意味します7。レキシカルバインディングは不定エクステント(indefinite extent)ももちます。これは、ある状況下において、クロージャー(closures)と呼ばれるスペシャルオブジェクトにより、バインディング構造が実行を終えた後でさえも、存続を続けることを意味します。

以降のサブセクションでは、ダイナミックバインディングとレキシカルバインディング、およびEmacs Lispプログラムでレキシカルバインディングを有効にする方法について、より詳細に説明します。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9.1 Dynamic Binding

デフォルトでは、Emacsにより作成されるローカル変数のバインディングは、ダイナミックバインディングです。ある変数がダイナミックにバインドされていると、Lispプログラムの実行における任意のポイントでのカレントバインディングは、単にそのシンボルにたいしてもっとも最近作成されたダイナミックなローカルバインディングか、そのようなローカルバインディングが存在しない場合はグローバルバインディングになります。

以下の例のように、ダイナミックバインディングはダイナミックスコープとダイナミック<エクステントをもちます:

(defvar x -99)  ; xは初期値として-99を受け取る。

(defun getx ()
  x)            ; この関数内では、xは“自由”に使用される。

(let ((x 1))    ; xはダイナミックにバインドされている。
  (getx))
     ⇒ 1

;; letフォームが終了した後、
;; xは前の値-99にリバートされる。

(getx)
     ⇒ -99

関数getxxを参照します。defun構造自体の中にxにたいするバインディングが存在しないと意味において、これは“自由”な参照です。xが(ダイナミックに)バインドされているletフォーム内からgetxを呼び出すと、ローカル値(つまり1)が取得されます。しかし、その後letフォームの外側からgetxを呼び出すと、グローバル値(つまり-99)が取得されます。

以下は、setqを使用してダイナミックに変数をバインドする、例をです:

(defvar x -99)      ; xは初期値として-99を受け取る。

(defun addx ()
  (setq x (1+ x)))  ; xに1追加して、新しい値をreturnする。

(let ((x 1))
  (addx)
  (addx))
     ⇒ 3           ; addxを2回呼び出すと、xに2回追加される。

;; letフォームが終了した後、
;; xは前の値-99にリバートされる。

(addx)
     ⇒ -98

Emacs Lispでは、ダイナミックバインディングは、シンプルな方法で実装されています。それぞれのシンボルは、シンボルのカレントのダイナミック値(または値の不在)を指定する値セルをもちます。Symbol Componentsを参照してください。あるシンボルがダイナミックなローカル値を与えられたとき、Emacsは値セルの内容(または値の不在)をスタックに記録し、新しいローカル値を値セルに格納します。バインディング構造が実行を終えたとき、Emacsはスタックから古い値をpopして、値セルにそれを置きます。


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9.2 Proper Use of Dynamic Binding

ダイナミックバインディングは、プログラムにたいしてテキスト的なローカルスコープ内で定義されていない変数を参照することを許す、強力な機能です。しかし、無制限に使用した場合は、プログラムの理解しにくくしてしまうこともあります。このテクニックを使用するために、2つの明解な方法があります:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9.3 Lexical Binding

Emacsのバージョン24.1から、オプションの機能としてレキシカルバインディングが導入されました。わたしたちは、この機能の重要さが、将来において重要になることを期待します。レキシカルバインディングは最適化の機会をより広げるので、この機能を使用するプログラムはおそらく、将来のEmacsバージョンで高速に実行されるようになるでしょう。レキシカルバインディングは、わたしたちがEmacsに将来追加したいと考える並列性(concurrency)とも互換をもっています。

レキシカルにバインドされた変数はレキシカルスコープ(lexical scope)をもいます。 これは、その変数にたいする参照は、そのバインディング構造内にテキスト的に配置されなければならないことを意味します。以下は例です (実際にレキシカルバインディングを有功にする方法は、Using Lexical Bindingを参照してください):

(let ((x 1))    ; xはレキシカルにバインドされる。
  (+ x 3))
     ⇒ 4

(defun getx ()
  x)            ; この関数内では、xは“自由”に使用される。

(let ((x 1))    ; xはレキシカルにバインドされる。
  (getx))
error→ Symbol's value as variable is void: x

ここでは、xはグローバル値をもちません。letフォーム内でレキシカルにバインドされたとき、この変数はletのテキスト境界内で使用できます。しかし、このlet内から呼び出されるgetx関数からは、getxの関数定義がletフォームの外側にあるので、使用することができません

レキシカルバインディングが機能する方法を説明します。各バインディング構造は、その構造および構造のローカル値でバインドされるシンボルを指定することにより、