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

関数定義の書き方

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

[back]


特殊形式 `defun'

関数定義は `defun' という単語に続けて、次のような最大五つの部分を加えたものである。

  1. 関数定義が付けられるシンボルの名前。
  2. 関数に渡される引数のリスト。もし一つも引数をつけない場合、ここは空リスト `()' にする。
  3. 関数を説明する文章。(技術的には省略可能であるが、書くことが強く望まれている。)
  4. 省略可能。この関数をインタラクティブにする、つまり `M-x' に続けて関数名をタイプするか、 適当なキーないしはキーコードをタイプすることで使うことが出来るようにするためのS式を書く。
  5. 計算機に何をすべきかを命令するコードを書く。即ち、関数定義の本体。

関数定義の例:

(defun multiply-by-seven (number)
    "Multiply NUMBER by seven."
    (* 7 number))

引数リストの中で使われる名前は、その特定の定義の中だけでしか使われないプライベートなものであるため、 どんな名前でも選ぶことが出来る。

`apropos' のような幾つかのコマンドは複数行に渡って書かれた説明文の文字列のうちの最初の一行だけ しか表示しないので、説明文字列の最初の一行は完結した一つの文にすべき。

`C-h f' (`describe-function') を使ったときに変な表示のされかたをするので、二行目も書く 場合はこれをインデントすべきではない。

関数定義のインストール

関数定義を評価することで、関数がEmacs を終了するまでインストールされる。古い関数定義を新しいバージョンに 置き換えるには、関数定義を書き直し、もう一度評価すれば良い。

関数をインタラクティブにする

インタラクティブな関数はユーザーが `M-x' に続けて関数の名前をタイプする、あるいは、その関数にバインドした キーをタイプすることで呼び出すことが出来る。関数をインタラクティブなものにするには、特殊形式 `interactive' で始まるリストを説明文字列のすぐ後に置く。

インタラクティブな関数の例:

(defun multiply-by-seven (number) ; インタラクティブバージョン
  "Multiply NUMBER by seven."
  (interactive "p")
  (message "The result is %d" (* 7 number)))

インタラクティブな関数の呼び出し方

  1. まず渡されるべき数を含む前置引数をタイプする。ついで `M-x' と関数名 をタイプする、例えば `C-u 3 M-x forward-sentence'、とする。
  2. あるいは、その関数にバインドされたキーないしはキーコードをタイプす る。例えば `C-u 3 M-e'。

`interactive' の他のオプション

"p" `interactive' の引数として `"p"'を使う場合、`C-u' に続けて数をタイプする か、`Meta' キーに続けて数をタイプすることにより、このコマンドに引数として数 を渡すことが出来る。
r `r' という文字の場合、Emacs はその関数にその時のリージョンの最初 と最後の位置 (その時のポイントとマークの値) を二つの別々の引数として渡す。
B `B' であれば、ミニバッファにプロンプトを出して、バッファの名前の入 力を促し、入力された値を関数に渡す。プロンプトには `B' に続く値が 使われる。例えば、`"BAppend to buffer: "' と記述する。
b 現在存在するバッファ。
f 現在存在するファイル。

関数に二つ以上の引数を渡したい場合、`interactive' に続けて複数の文字列を 付け加えることで、各々の引数に情報を渡すことが出来る。この場合その情報は、 各々の引数に `interactive' に書いたのと同じ順序で渡される。例えば `"BAppend to buffer: "' に続けて `\n' と `r' を書くことで、Emacs はプロンプトでバッファ 名を要求すると同時にポイントとマークの値もその関数に渡す。以下この場合の関数の形式:

(defun 関数名 (buffer start end)
  "説明文字列..."
  (interactive "BAppend to buffer: \nr")
  関数の本体...)

上に挙げたような特定の文字による引数の与え方が目的に合わない場合、独自の引数をリストとして `interactive' に渡すことも出来る。

コードをずっとインストールしておくには

関数定義のコードを`.emacs'の中に書きことにより、Emacs を起動した時にこの`.emacs'が自動的に評価され、 その中に書かれた全ての関数がインストールされる。

また、インストールしたい関数の定義を一つのファイル、もしくは関数ごとに複数のファイルに書いておき、 `load' という関数を使って Emacs にそれを評価させてそれらの関数をイン ストールする。サイト全体でそのコードを使いたい場合は、普通はその関数を`site-init.el' 呼ばれるファイルに書いておく。

`let'

`let'はその `let' 式の外にある同じ名前の変数からは隔離されている変数、 即ち、"ローカル変数" ("local variable") と呼ばれるものを発生させる。

`let' は一度に複数の変数を発生させることが出来、各々の変数に初期値(特に指定しなければ`nil')を設定する。

`let' 式の構成部分

`let' というS式は三つの部分からなるリストである。各々、

  1. シンボル `let'
  2. "変数リスト" ("varlist")
    • 単独のシンボル:初期値には `nil' が設定される。
    • 最初の要素がシンボルであるような二つの要素からなるリスト: 二番目の要素を評価した時に返される値が、初期値として一番目のシンボルに設定される。
  3. 大抵、一つないしは複数のリストからなる`let' 式の本体

`let' 式の例

次のS式は二つの変数 `zebra' と `tiger' を発生させ、それに対して初期値を与えている。 `let' 式の本体は関数 `message' を呼び出すリストである。

(let ((zebra 'stripes)
      (tiger 'fierce))
      (message "One kind of animal has %s and another is %s."
          zebra tiger))

特殊形式 `if'

特殊形式 `if'は計算機になんらかの判断をさせる時に使われる。

特殊形式 `if'は、最初の要素に`if' を、二番目においてテスト部分、三番目に実行部分の三つの要素をもつリストである。 普通`if' 式が書かれる場合、真か偽かのテストは、`if' と同じ行に書かれ、テストが真であった場合に実行される "then-part" は二行目以降に書かれる。

例:

(if (> 5 4) ; if-part
    (message "5 is greater than 4!"))  ; then-part

真偽テスト (true-or-false-test) の部分は List インタプリタにより評価されるS式である。

If--then--else 式

`if' 式は、オプションとして "else-part" と呼ばれる、真偽テストが偽を返した場合のための、三番目の要素を持つことが出来る。

Lisp のコードを書く場合、else-part は新しく改行してから then-part よりは少ないインデントで書き始める。

例:

(if (> 4 5) ; if-part
    (message "5 is greater than 4!")  ; then-part
  (message "4 is not greater than 5!")) ; else-part

Lisp における真と偽

真であるか否かテストされるS式は、評価した結果が `nil' 以外の値であれば "true" と判断される。 Lisp ではシンボル `nil' は「空リスト」と「偽」の二つの意味を持つ。Lisp にとっては、`()' と `nil' は全く同じものである。 もしテストで真を返すような適当な値が見つからなければ、Lisp インタプリタは真を表わすためにシンボル `t' を返す。

例:

(> 5 4)

その他の関数

`equal' `eq'
二つのオブジェクトが同じであるかどうかをテストする。`equal' の方は、 両者が同じ構造と中身を持ちさえすれば、真を返す。一方、`eq' の方は、 引数が両方とも実際に同じオブジェクトである時のみ真を返す。