ラムダ式では、ラムダリストの直後にドキュメント文字列を任意で記述できます。この文字列は関数の実行に影響を与えません。一種のコメントではありますが、Lispの世界に実際に存在し、Emacsのヘルプ機能で利用可能な体系化されたコメントです。ドキュメント文字列へのアクセス方法については、Documentationを参照してください。
プログラム内のすべての関数に、たとえプログラム内部からのみ呼び出されるものであっても、ドキュメント文字列を用意しておくとよいでしょう。ドキュメント文字列はコメントに似ていますが、より簡単に参照できる点が異なります。
ドキュメント文字列の1行目は、apropos
がこの1行目のみを表示するため、それだけで完結している必要があります。そこには、関数の目的をまとめた1〜2文の完全な文章を記述してください。
ドキュメント文字列の先頭は、通常ソースファイル内でインデントされますが、これらのスペースは開始ダブルクォートの前にあるため、文字列の一部ではありません。プログラムソース内でテキストが縦に並ぶように、文字列のそれ以降の行をインデントすることを習慣にしている人もいます。それは間違いです。 後続行のインデントは文字列内部にあるため、ソースコード上では見栄えが良くても、ヘルプコマンドで表示されると見栄えが悪くなります。
ドキュメント文字列の後には、必ず少なくとも1つのLisp式が続かなければなりません。そうでない場合、それはドキュメント文字列ではなく、本体の単一の式となり、戻り値として使用されます。関数から返す意味のある値がない場合は、ドキュメント文字列の後に
nil を付加して返すのが慣例となっています。
ドキュメント文字列の最終行では、実際の関数引数とは異なる呼び出し規約を指定できます。次のようなテキストを記述してください:
\(fn arglist)
空行の後、行頭に配置され、ドキュメント文字列内ではその後に改行が続かない形式です。(‘\’ は、Emacs のモーションコマンドとの混同を避けるために使用されています。)このように指定された呼び出し規約は、関数の実際の引数から導出されるものの代わりに、ヘルプメッセージに表示されます。
この機能は特にマクロ定義において有用です。というのも、マクロ定義に記述される引数は、ユーザーがマクロ呼び出しの各部分をどのように捉えているかと一致しないことが多いためです。
呼び出し規約を非推奨とし、上記の仕様で規定した規約を優先させたい場合は、この機能を使用しないでください。代わりに、advertised-calling-convention 宣言(declare 形式を参照)または
set-advertised-calling-convention(関数の非推奨化を参照)を使用してください。これら2つを使用すると、バイトコンパイラが非推奨の呼び出し規約を使用する
Lisp プログラムをコンパイルする際に警告メッセージを出力するようになります。
(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)
を記述することで、ドキュメント文字列を動的に生成することも可能です。これにより、関数が定義される実行時に form が評価され、それがドキュメント文字列として使用されます15。さらに、関数のシンボルの 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"