Practical Common Lispの最初の例(データベースの例)では、作成者はマクロといくつかのサポート関数を使用して、という名前のより大きな関数を置き換えwhere
ます。が関数の場合、コードwhere
は正常に機能しますが、マクロの設定では「未定義の変数」および「バインドされていない変数」のエラーが返されます。(元の関数をコメントアウトし、Emacsを再起動し、where
マクロを追加したらファイルを再コンパイルしたことに注意してください。)
例によれば、マクロはでROW
はなくで評価する必要があるため、REPLでキャッチされたスタイル警告は私にとって最も疑わしいものです。CD
なぜROW
未使用なのですか?この警告を解決するにはどうすればよいですか?
これはREPLに出力されます:
; in: SELECT (WHERE :TITLE "Animals" :RIPPED T)
; (WHERE :TITLE "Animals" :RIPPED T)
; ==>
; #'(LAMBDA (ROW)
; (AND (EQUAL (GETF CD :TITLE) "Animals") (EQUAL (GETF CD :RIPPED) T)))
;
; caught STYLE-WARNING:
; The variable ROW is defined but never used.
; in: SELECT (WHERE :TITLE "Animals" :RIPPED T)
; (WHERE :TITLE "Animals" :RIPPED T)
; --> FUNCTION AND IF EQUAL
; ==>
; (GETF CD :TITLE)
;
; caught WARNING:
; undefined variable: CD
;
; compilation unit finished
; Undefined variable:
; CD
; caught 1 WARNING condition
; caught 1 STYLE-WARNING condition
これは、デバッグスペースに出力されます。
The variable CD is unbound.
[Condition of type UNBOUND-VARIABLE]
これが私の.lispファイルのサポート関数とマクロです:
; this function is used in both implementations. *db* is a (global) database
(defun select (selector-fn)
(remove-if-not selector-fn *db*))
(defun make-comparison-expr (field value)
`(equal (getf cd ,field) ,value))
(defun make-comparisons-list (fields)
(loop while fields
collecting (make-comparison-expr (pop fields) (pop fields))))
(defmacro where (&rest clauses)
`#'(lambda (row) (and ,@(make-comparisons-list clauses))))
私はSBCL、Emacs、Slimeを使用しています。