ラムダ式はラムダリストの直後に、オプションでドキュメント文字列(documentation string)をもつことができます。この文字列は、その関数の実行に影響を与えません。これはコメントの一種ですがLisp機構に内在するシステム化されたコメントであり。Emacsのヘルプ機能で使用できます。ドキュメント文字列にアクセスする方法は、ドキュメントを参照してください。
たとえその関数があなたのプログラム内だけで呼び出される関数だとしても、すべての関数にドキュメント文字列を与えるのはよいアイデアです。ドキュメント文字列はコメントと似ていますが、コメントより簡単にアクセスできます。
ドキュメント文字列の1行目は、関数自体にもとづくものであるべきです。なぜならapropos
は、最初の1行目だけを表示するからです。ドキュメント文字列の1行目は、その関数の目的を要約する1つか2つの完全なセンテンスで構成されるべきです。
ドキュメント文字列の開始は通常、ソースファイル内ではインデントされていますが、ドキュメント文字列の開始のダブルクォート文字の前にインデントのスペースがあるので、インデントはドキュメント文字列の一部にはなりません。ドキュメント文字列の残りの行がプログラムソース内で揃うようにインデントする人がいます。これは間違いです。後続の行のインデントは文字列の内部にあります。これはソースコード内での見栄えはよくなりますが、ヘルプコマンドで表示したとき見栄えが悪くなります。
ドキュメント文字列がなぜオプションになるのか不思議に思うかもしれません。なぜならドキュメント文字列の後には必須となる関数の構成要素であるbodyが続くからです。文字列を評価するとその文字列自身がリターンされるので、それがbody内の最後のフォームでない限りなんの効果もありません。したがって実際はbodyの1行目とドキュメント文字列で混乱が生じることはありません。bodyの唯一のフォームが文字列なら、それはリターン値とドキュメントの両方の役目を果たします。
ドキュメント文字列の最後の行には、実際の関数引数とは異なる呼び出し規約を指定できます。これは以下のようなテキストを記述します
\(fn arglist)
そのテキストの後に空行を配置して、テキスト自身は行頭から記述、ドキュメント文字列内でこのテキストの後に改行が続かないように記述します(‘\’はEmacsの移動コマンドが混乱するのを避けるために使用する)。この方法で指定された呼び出し規約は、ヘルプメッセージ内で関数の実引数から生成される呼び出し例と同じ場所に表示されます。
マクロ定義内に記述された引数は、ユーザーがマクロ呼び出しの一部だと考える方法とは合致しない場合がしばしばあるので、この機能はマクロ定義で特に有用です。
呼び出し規約を廃止して上記の仕様で示す規約を公開したければ、この機能を使用してはなりません。かわりに廃止された呼び出し規約を使用するLispプログラムのバイトコンパイル時に警告メッセージを発する宣言advertised-calling-convention
(declare
フォームを参照)かset-advertised-calling-convention
(関数の陳腐化の宣言を参照)を使用してください。
(fn)
機能が使用される典型的な状況には以下が考えられます:
(defmacro lambda (&rest cdr) "… \(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"…)
(defmacro macroexp--accumulate (var+list &rest body) "… \(fn (VAR LIST) BODY…)" (declare (indent 1)) (let ((var (car var+list)) (list (cadr var+list)) …)))
defalias
の目的についてのより詳細な説明。たとえば:
(defalias 'abbrev-get 'get "… \(fn ABBREV PROP)")
ドキュメント文字列は通常だと静的ですが、動的な生成を要するときもあるかもしれません。コンパイル時にドキュメント文字列と一緒に関数コードを生成するマクロを記述することでこれを達成できる場合もあります。しかしドキュメント文字列のかわりに(:documentation
form)
を記述することで、doc文字列を動的に生成することもできます。これは実行時に関数が定義されるとformを評価して、それをドキュメント文字列として使用します12。関数のシンボルのfunction-documentation
プロパティに文字列に評価されるLispフォームをセットすれば、オンザフライでドキュメント文字列を算出することもできます。
たとえば:
(defun adder (x) (lambda (y) (:documentation (format "Add %S to the argument Y." x)) (+ x y))) (defalias 'adder5 (adder 5)) (documentation 'adder5) ⇒ "Add 5 to the argument Y."
(put 'adder5 'function-documentation '(concat (documentation (symbol-function 'adder5) 'raw) " Consulted at " (format-time-string "%H:%M:%S"))) (documentation 'adder5) ⇒ "Add 5 to the argument Y. Consulted at 15:52:13" (documentation 'adder5) ⇒ "Add 5 to the argument Y. Consulted at 15:52:18"