【发布时间】:2018-11-12 19:26:54
【问题描述】:
在我之前的问题中,@sds 回答得非常好,
How to wrap and execute a lisp s-expression by another s-expression?
我们来到了动态和静态宏的话题。
@sds 对我的with-open-files 宏问题的静态解决方案是:
(defmacro with-open-files ((streams file-names &rest options &key &allow-other-keys) &body body)
(if (and streams file-names)
`(with-open-file (,(pop streams) ,(pop file-names) ,@options)
(with-open-files (,streams ,file-names ,@options)
,@body))
`(progn ,@body)))
还有他的动态解决方案:
(defmacro with-open-files-d ((streams file-names &rest options &key &allow-other-keys) &body body)
(let ((sv (gensym "STREAMS-"))
(ab (gensym "ABORT-"))
(op (gensym "OPTIONS-")))
`(let ((,sv ,streams)
(,ab t)
(,op (list ,@options)))
(progv ,sv (mapcar (lambda (fn) (apply #'open fn op)) ,file-names)
(unwind-protect (multiple-value-prog1 (progn ,@body) (setq ,ab nil))
(dolist (s ,sv)
(when s
(close s :abort ,ab))))))))
我的问题是:在宏中使用宏是否会自动禁止它是动态的? (我想是的......,因为宏定义中的宏调用必须在编译之前执行,不是吗?或者不是?)。
以及何时使用静态或动态宏解决方案? - 当然,如果数据仅在运行时已知,则需要一个动态宏,不是吗? 什么是最佳做法?
【问题讨论】:
-
DOLIST是一个宏,您在动态版本中使用它。所以显然它并没有禁止它。 -
你应该使用能产生最清晰的代码来解决问题的任何一种形式。
-
@Barmar true ...但是 with-open-files 禁止它...也许是因为它需要一个字面使用的参数? (例如流变量?) ...
-
对。在运行时计算值时,不能使用需要编译时文字的宏。
标签: dynamic static macros common-lisp