我正在通过 Practical Common Lisp 工作。我得到了定义 deftest
的示例。类似于 defun
的宏增加了一些功能。这让我想到能够添加一个文档字符串会很好。我发现以下两项都有效,但其中一项更正确吗?是否有一种“正确”的方式来实现 defun
的类似可选文档字符串的行为? ?
(defmacro deftest (name parameters &body body)
(let ((docstring ""))
(when (stringp (car body)) (setf docstring (car body) body (cdr body)))
`(defun ,name ,parameters
,docstring
(let ((*test-name* (append *test-name* (list ',name))))
,@body))))
(defmacro deftest (name parameters &optional docstring &body body)
(when (not (stringp docstring)) (setf docstring ""))
`(defun ,name ,parameters
,docstring
(let ((*test-name* (append *test-name* (list ',name))))
,@body)))
最佳答案
通常,您可能希望从函数体中解析出可能的文档字符串和任何声明,因此您可以将声明放在它们所属的位置。我使用这样的东西:
(defun parse-body (body)
(multiple-value-bind (docstring decls/forms)
(if (stringp (first body))
(values (first body) (rest body))
(values nil body))
(loop for remainder on decls/forms
while (and (not (null remainder))
(consp (first remainder))
(eql (car (first remainder)) 'declare))
collect (first remainder) into decls
finally (return (values docstring decls remainder)))))
然后你的deftest
将会(defmacro deftest (name parameters &body body)
(multiple-value-bind (docstring decls forms) (parse-body body)
`(defun ,name ,parameters
,@(if docstring (list docstring) '())
,@decls
(let ((*test-name* (append *test-name* (list ',name))))
,@forms))))
我希望我可以说我有一个标准 parse-body
功能,但我没有:我只是每次都写一个新的。
关于lisp - 将文档字符串合并到 def* 宏中的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66364347/