読者です 読者をやめる 読者になる 読者になる

List 処理

この文章は Programming in Emacs Lisp の中から、個人的に重要と思われたポイントを抜き出してまとめた物です。 従って内容は、これを超えるものではありません。さらに詳細な説明については、上記ページを読ま れることをお勧めします。

[back]


Listとは

Lisp のプログラムはリストもしくは単一のアトム からなるS式で出来ている。リストは0以上のアトムもしくはリストからなる。これらは空白文字で区切 られており、括弧で囲まれている。リストの中身は空であっても良い。

Lisp の中では、データとプログラムの両方が同じ様に表現される。

リストの例

'(this list has (a list inside of it))

このリストの構成要素は、`this', `list', `has', という単語と、`(a list inside of it)' という リストである。内部にある方のリストは、`a', `list', `inside', `of', `it' という単語からなってい る。

Lisp のアトム

アトムは幾つかの文字からなるシンボルである。例えば

  • `forward-paragraph'
  • 一つの文字からなる `+'
  • 二重引用符に両側を挟まれた文字列からなる文字列
  • 数値

リストの中では各々のアトムは互いに空白で区切られている。また括弧のすぐ 隣りに位置することが出来る。中に何も入っていないリストというのは `()' であるが、これは "空リスト"("null list") と呼ばれる。アトムやリストを表示したものは、 "symbolic-expression", もしくはもっと簡単に "S式"と呼ばれる。二つの二重引用符で挟まれたテキストはアトムである。この種のアトムは "文字列" ("string")と呼ばれる。

GNU Emacs によるリストのタイプの支援

リージョン内のコードをきちんとインデントしてくれるコマンドは、`M-C-\' にバインドされている。

シンボル

Lisp では、ある命令セットには幾つかの名前が付随している。一つのシンボルは、一度にただ一つの 関数定義しか持つことが出来ない。 Lisp の中では、 シンボルは、関数定義を持つことが出来るのと同様に、ある値を持つことが出来る。

通常、関数が属する Emacs のパートが識別出来るような シンボルの名前を付け方をする。例えばTexinfo を扱うための関数の名前は全て `texinfo-' で始まる。

プログラムの実行(評価)

Lisp インタプリタがあるS式を処理している時、その動作は "評価"("evaluation") と呼ばれ、以下のように動作する。

  1. list の頭に、引用符が付いているか見る。
  2. もし付いていれば、単にそのリストを我々に渡す。
  3. 一方、付いていない場合はリストの先頭の要素を見に行き、それが関数の定義を持っているかどうかを調べる。
  4. 定義されている場合はその定義にある命令を実行する。
  5. そうでなければエラーメッセージを表示する。

インタプリタは値を返すと同時に、カーソルを動かしたり、ファイルをコピーしたりといった他の動作 も行う。このような動作は、"副作用" ("side effect") と呼ばれる。

引用符 “`” があると Lisp インタプリタはその後に続くS式を書かれたままの形で返し、引用符が 無い場合のように評価したりはしない。リストの頭に引用符が付いていない場合は、計算機が従うべき命 令になる。(Lisp ではこれらの命令は 関数(*function*) と呼ばれる。)

引用符が付いておらず、括弧に囲まれてもいない単独のシンボルを、Lisp インタプリタ変数("variable") として評価しようとする。

幾つかの"特殊形式" ("special form") と呼ばれる関数はその特殊性のために普通のやり方ではうまく 働かない。

Lisp インタプリタは常に一番内部のリストから処理していく。それ以外の場合は、インタプリタは左か ら右へS式を一つずつ処理していく。

数値は評価されるとそれ自身を返し、二重引用符で挟まれた文字列を評価した時もそれ自身を返す。シ ンボルそのものを評価すると、その値が返される。

emacs上では、カーソルを次のリストの右側の括弧のすぐ後に持ってきて、`C-x C-e' とタイプしてリス トを評価することが出来る。

内部のリストの評価

外側のリストが評価される時は、内部のリストを評価した時に返った値が情報として用いられる。Lisp の中では、数字を評価した場合、その値自身が返され、シンボルを先頭に持つリストの直後でS式を評価 したなら、返された値はその名前に付随する関数の定義の中の命令を計算機が実行した結果が返ってくる。

バイトコンパイル

Lisp インタプリタは人間が読めるコードとバイトコンパイル("byte compile") されたコードの二つの種類の物を解釈出来る。バイトコンパイルされたコードは我々が読めるコードよりも 速く走らせることが出来る。人間が読めるコードをバイトコンパイルされたコードに変換することも出来る。 これは `byte-compile-file' 等の、コンパイルコマンドを走らせることによって行う。

関数

関数とは計算機が従うべき命令の集まりのことである。Lispでは、頭に引用符が付いていないリストはあ る命令を実行する。これらの命令を関数(*function*)と呼ぶ。全ての関数は C 言語で書かれた少数の "プリミティブ" ("primitive")な関数を除いて、別の関数を使って定義されている。Emacs Lisp のコードを 書く場合、C で書かれた関数を使う場合とEmacs Lisp で書かれた関数を使う場合とで区別をつける必要は全 くない。

引数

Lisp の中では関数に対する引数は関数に続くアトム もしくはリストである。これらのアトムやリストを評価して 返された値が関数に渡されることになる。異なる関数は異なる数の引数を取り得る。また、全く引数を 取らない関数もある。

引数は評価された時に値を返すシンボル、即ち変数の値やリストであることも可能。例えば、

(+ 2 fill-column)

可変な数の引数をとることも出来る。例えば `concat', `+', `*' といった幾つかの関数では引数の数は 固定されていない。

関数に渡されるデータの型はその関数がどんな種類の情報を必要としているかによる。以下に例を示す。

  • concat:二つ以上のテキストの文字列を連結ないしは合成して一つの文字列を作る関数。この場合の引数は文字列。
    (concat "abc" "def")
  • substring:文字列である最初の引数の部分文字列を返す関数。引数として文字列と数値の両方を取る。
    (substring "The quick brown fox jumped." 16 19)

関数 `message'

`message' という関数はユーザにメッセージを送るものもで、メッセージをエコー領域に表示する。 引数の数は固定されていない。

例:二重引用符に狭まれた文字列全体が一つの引数になっており、その全体が表示される。

(message "This message appears in the echo area!")

%s' が二重引用符に挟まれた文字文字列に入っていたとしたら、関数 `message' は文字列に続く二番目 の引数を評価し、その結果を `%s' のある所に代入して表示する。値を10進数として表示するには、`%d' と いう文字列を使う。もし一つ以上の`%s'ないしは`%d'が二重引用符で狭まれた文字列の中にあったとすると、 最初の `%s' の位置にはその文字列に続く最初の引数の値が表示され、二番目の`%s' の位置には二番目の 引数の値が表示され... という具合になる。

変数

Lisp の中では、シンボルは、 関数定義を持つことが出来るのと同様に、ある値 を持つことが出来る。値としてのシンボルを"変数"("variable")と呼ぶ。

関数定義
計算機が従うべき命令の集まり
数値とか名前のように、何か変化し得るもの

シンボルや数値、リスト文字列等、どんな LispS式もシンボルの値になり得る。

`set' もしくは `setq'という関数を使うことで変数に値を格納することが出来る。別の方法として、 `let' を使うことでも変数に値を格納することが出来る。

`set' の利用

以下のS式を評価する。

(set 'flowers '(rose violet daisy buttercup))

すると、`(rose violet daisy buttercup)' というリストがエコー領域に返され、副作用としてシン ボル `flowers' が、このリストにバインドされる。`set' を利用する時は、`set' の引数には、それら を評価しようとする場合を除いて、必ず引用符を付ける必要がある

`setq' の利用

特殊形式 `setq'は、`set' と引用符付きの第一引数の組み合わせという極めてよく使われるものに、 名前を付けたものである。第一引数に自動的に引用符を付ける以外、`set' とほぼ同じである。`setq' は、一つのS式の中で複数の異なる変数に対して各々に異なる値をセットすることが出来る

使用例:

  • `setq' を使って `carnivores' という変数に `'(lion tiger leopard)' という リストをセットする:
    (setq carnivores '(lion tiger leopard))
  • 異なる変数の各々に異なる値をセットする:
    (setq trees '(pine fir oak maple) herbivores '(gazelle antelope zebra))

`set' や `setq' は、あるシンボルを特定のリストへの*ポイント*にする働きをするという捉え方もできる。

カウント

`setq' をカウンタとして利用する方法:

(setq counter 0)                ; イニシャライザ
(setq counter (+ counter 1))    ; インクリメンタ
counter                         ; カウンタ

イニシャライザでカウンタに0をセットし、次に二番目のインクリメンタのS式 `(setq counter (+ counter 1))' を評価すると、カウンタは一つ増える。その後も二番目のS式を評価するごとに値は増えていく。

シーケンス:

  1. `counter'の評価、戻り値はそのときの値。
  2. 1が評価、戻り値は1。
  3. `counter'の戻り値と1が引数として+に渡され、`(+ counter 1)'が評価される。戻り値は`counter'と1の和。
  4. `(+ counter 1)'の戻り値が引数として`setq'に渡され、カウンタに新しい値が設定される