単一のLISPファイルのコードはどの順序で整理する必要がありますか?他のLISPプログラマがコードを簡単に理解できるようにする一般的なスタイルガイドラインはありますか?
LISPスタイルガイドライン をグーグルすると、多くの結果が得られます。その中で:
ただし、関数やその他の定義を単一のソースファイル内でどのように編成する必要があるかについては、説明していません。
「クリーンコード」によってMartin Fowler(これは特にLISPを対象としていません)は、関数/メソッドを上から下に整理することを推奨しています:最初にコードを抽象的に記述し、次に詳細に深く掘り下げます。私の意見では、これは関数定義を整理するための良い方法です。
ただし、関数定義を上から下に並べると、SBCL REPLはcaught STYLE-WARNING: undefined function: …
LISPファイルをロードするとき。したがって、SBCLは、関数を定義する前にその関数を使用することは悪いスタイルだと考えています。
定義の順序のベストプラクティスは何ですか?コンパイラー/インタープリターの警告を出さないことが望ましい。
一般的なLISPには COMPILE
と COMPILE-FILE
の両方があります。
たとえば、ファイル全体をコンパイルする場合、SBCLのような実装は未定義の関数について警告しません。スライムの下で C-c M-k 警告をトリガーしません:
(defun bar (x) (foo x))
(defun foo (y) (+ 3 y))
コンパイルした後、.fasl
をロードしても、新しいLISPイメージに警告が表示されませんが、.LISP
をロードすると、ソースファイルの LOAD
すべてのフォームを順番に実行するだけです。
しかし、私が見たほとんどのコードは、低レベルの要素から物事を定義し、ファイルの後半で高レベルの関数を構築します。個人的には、逆の順序よりもこの順序で混乱することはないと思います。これは、flet
またはlabels
を使用してローカル関数を定義する方法、またはlet
を使用してローカル変数を定義する方法と非常に一貫しています。相互に再帰的な関数を定義する必要がある場合は、定義する前に関数を宣言することもできます。
(declaim (ftype function foo bar baz ...))
LISP環境は、関数とメソッドの定義に移動する効率的な方法をサポートしているため、通常はslime-edit-definition
に依存しています。
IMOがコードを編成する上で最も重要なのは、おそらくパッケージとそれらがどのように相互に関連するかについて考えることです。