コンパイルは、Common Lispの中で定義されていますCLHS Section 3.2.3 File Compilation
コンパイル中:読み込みマクロを使用してフォームを利用するために、あなたはそれがコンパイラで使用可能なマクロの実装を読んで確認する必要があります。
通常、このような依存関係は、システムのさまざまなファイル間の依存関係(プロジェクトなど)が記述されているdefsystem
機能で処理されます。特定のファイルをコンパイルするためには、コンパイルされたLispに別のファイル(コンパイルされたバージョンが望ましい)をロードする必要があります。
ここで、読み込みマクロを定義し、同じファイル内に表記法を使用してフォームを作成する場合は、読み込みマクロとその実装についてコンパイラが認識していることを確認する必要があります。ファイルコンパイラにはコンパイル環境があります。デフォルトでは、同じファイルのコンパイル済み関数をこの環境にロードしません。
コンパイラがファイル内の特定のコードを認識できるようにするため、Common LispはEVAL-WHEN
を提供します。
はさんが読んマクロの例を見てみましょう:
(set-syntax-from-char #\] #\))
(defun reader-example (stream char)
(declare (ignore char))
(let ((class (read stream t nil t))
(args (read-delimited-list #\] stream t)))
(apply #'make-instance
class
args)))
(set-macro-character #\[ 'reader-example)
(defclass example()
((name :initarg :name)))
(defvar *examples*
(list [example :name e1]
[example :name e2]
[example :name e3]))
あなたは上記のソースをロードする場合、すべてが正常です。しかし、ファイルコンパイラを使用すると、最初にロードすることなくコンパイルされません。例えば、ファイルコンパイラは、パス名で関数COMPILE-FILE
を呼び出すことによって呼び出されます。今ファイルのコンパイル
:上記
(set-syntax-from-char #\] #\))
は、コンパイル時に実行されることはありません。新しい構文の変更はコンパイル時には利用できません。
(defun reader-example (stream char)
(declare (ignore char))
(let ((class (read stream t nil t))
(args (read-delimited-list #\] stream t)))
(apply #'make-instance
class
args)))
上記の関数はコンパイルされますが、ロードされません。この実装は、後の手順でコンパイラで使用することはできません。
(set-macro-character #\[ 'reader-example)
上記のフォームも実行されません。コードが生成されます。
(defclass example()
((name :initarg :name)))
コンパイラはクラスを書き留めますが、後でそれをインスタンス化することはできません。
(defvar *examples*
(list [example :name e1]
[example :name e2]
[example :name e3]))
上記のコードは、読み込みマクロがコンパイル時に使用できないため、前に読み込まれていない限り、エラーをトリガーします。
- は別のファイルに読み取りマクロの実装を入れて、それがコンパイルされ、リードマクロを使用するすべてのファイルの前にロードされていることを確認してください。
は現在、2つの簡単な解決策があります。
- は、コンパイル時に効果を持っている必要があり、コードの周りに
EVAL-WHEN
を置く:
例:
(EVAL-WHEN (:compile-toplevel :load-toplevel :execute)
(do-something-also-at-compile-time))
上記は、コンパイラによって見ても、その後に実行されます。コンパイル時に、コードに必要なすべての定義があることを確認する必要があります。
言うまでもなく、このようなコンパイルの依存性をできるだけ減らすことは良いスタイルです。通常は、必要な機能を別のファイルに置き、このファイルがコンパイルされ、それを使用するファイルをコンパイルする前にコンパイルLispにロードされていることを確認してください。
実際には、SBCLには解釈モードがあり、デフォルトではオフになっています。http://www.sbcl.org/manual/Interpreter.html –
一般的なLispコンパイルはインクリメンタルですが、ファイルのコンパイルはわずかに異なります。 –
@Rainerあなたは精巧にできますか?私はそれに精通していません –