Next: , Previous: , Up: 関数   [Contents][Index]


13.4 関数の定義

わたしたちは通常は関数を最初に作成したときに名前を与えます。これは関数の定義(defining a function)と呼ばれており、通常はdefunマクロにより行われます。このセクションでは関数を定義する別の方法も説明します。

Macro: defun name args [doc] [declare] [interactive] body…

defunは新たなLisp関数を定義する通常の方法である。これは引数リストargs、およびbodyにより与えられるbodyフォームとともに、シンボルnameを関数として定義する(引数リストの機能を参照)。nameargsをクォートする必要はない。

docが与えられたら、それはその関数のドキュメント文字列を指定する文字列であること(関数のドキュメント文字列を参照)。declareが与えられたら、それは関数のメタデータを指定するdeclareフォームであること(declareフォームを参照)。interactiveが与えられたら、それは関数が対話的に呼び出される方法を指定するinteractiveフォームであるこ(インタラクティブな呼び出しを参照)。

defunのリターン値は定義されていません。

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

(defun foo () 5)
(foo)
     ⇒ 5

(defun bar (a &optional b &rest c)
    (list a b c))
(bar 1 2 3 4 5)
     ⇒ (1 2 (3 4 5))
(bar 1)
     ⇒ (1 nil nil)
(bar)
error→ Wrong number of arguments.

(defun capitalize-backwards ()
  "Upcase the last letter of the word at point."
  (interactive)
  (backward-word 1)
  (forward-word 1)
  (backward-char 1)
  (capitalize-word 1))

Emacsの関数のほとんどはLispプログラムのソースコードの一部であり、実行前にEmacs Lispリーダーがプログラムソースを読み込んだ際に定義される。しかし実行時にダイナミックに関数を定義することもできる(プログラムのコード実行時にdefun呼び出しを生成する)。関数の定義にジャンプするボタンを*Help*バッファーに表示するC-h fのようなEmacsのヘルプコマンドが、ソースコードを発見できないかもしれないので、これを行う際には注意を要する。なぜなら関数のダイナミックな生成は、defunにたいする通常の静的な呼び出しと比べて普通は非常に異なって見えるからである。このような関数を生成するコードを見つける作業を容易にするためにdefinition-nameプロパティを用いることができる。シンボルの標準的なプロパティを参照のこと。

意図せず既存の関数を再定義しないように注意されたい。defuncarのようなプリミティブ関数でさえ、問い合わせせずに躊躇なく再定義する。Emacsがこれを妨げることはない。なぜなら関数の再定義は故意に行われることがあり、そのような意図した再定義を、意図しない再定義と見分ける方法はがないからである。

Function: defalias name definition &optional doc

この関数は定義がdefinitionであるような関数としてシンボルnameを定義する。definitionには有効な任意のLisp関数、マクロ、スペシャルフォーム(スペシャルフォームを参照)、キーマップ(キーマップを参照)、ベクター、文字列(キーボードマクロ)を指定できる。defaliasのリターン値は未定義

docが非nilなら、それは関数nameのドキュメントとなる。それ以外ならdefinitionにより提供されるドキュメントが使用される。

内部的にはdefaliasは、通常は定義のセットにfsetを使用する。しかしnamedefalias-fset-functionプロパティをもつなら、fsetを呼び出すかわりにそれに割り当てられた値を使用する。

defaliasを使う正しい場所は、特定の関数やマクロの名前が正に定義される場所 — 特にソースファイルがロードされるときに明示的にその名前が出現する場所である。これはdefaliasdefunと同じように、どれが関数を定義するファイルなのか記録するからである(アンロードを参照)。

それとは対照的に他の目的のために関数を操作するプログラムでは、そのような記録を保持しないfsetを使用するほうがよいだろう。関数セルの内容へのアクセスを参照のこと。

Function: function-alias-p object &optional noerror

objectが関数のエイリアス(alias: 別名)かどうかをチェックする。エイリアスならその関数のエイリアスのチェーン(chain: 連鎖)を表すシンボルのリスト、エイリアスでなければnilをリターンする。たとえばabのエイリアスで、bcのエイリアスなら:

(function-alias-p 'a)
    ⇒ (b c)

定義中にループがあるとエラーをシグナルする。noerrorが非nilの場合には、ループしていないチェーン部分をリターンする。

defundefaliasで新たなプリミティブ関数を作成することはできませんが、任意の関数定義を変更するのに使用することができ、通常の定義がプリミティブであるcarx-popup-menuのような関数でさえ変更することができます。しかしこれは危険なことです。たとえばLispの完全性を損なうことなく、carを再定義するのはほとんど不可能だからです。それほど有名ではないx-popup-menuのような関数の再定義では、危険は減少しますが、それでも期待したとおりに機能しないかもしれません。Cコードにそのプリミティブの呼び出しがあれば、それは直接そのプリミティブのC定義を呼び出すので、シンボル定義を変更してもそれらに影響はありません。

defsubstも参照してください。これはdefunのように関数を定義して、それのインライン展開を処理するようLispコンパイラーに指示します。インライン関数Inliを参照してください。

関数名を未定義にするにはfmakunboundを使用します。関数セルの内容へのアクセスを参照してください。