首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在普通lisp宏中正确使用符号属性列表

如何在普通lisp宏中正确使用符号属性列表
EN

Stack Overflow用户
提问于 2022-04-01 22:20:30
回答 1查看 28关注 0票数 0

我正在编写一个Common宏define-computation,它以特定的方式定义函数,并通过向定义函数的符号的属性列表中添加一个属性:computation来标记它们。

define-computation正在寻找具有:computation属性集的函数的函数的表单,并使用特定的代码对它们进行包装。

当我在REPL中工作时,下面的代码按预期工作,宏展开允许我验证定义的-计算是否由supervise-computation正确地包装。

代码语言:javascript
复制
CL-USER> (macroexpand-1 '(define-computation c-2 ()
  (c-1)
  (format t "~&Compute something 2")))
(PROG1
    (DEFUN C-2 ()
      (DECLARE (OPTIMIZE (SAFETY 3) (SPACE 3)))
      (SUPERVISE-COMPUTATION
        (C-1))
      (FORMAT T "~&Compute something 2"))
  (EXPORT 'C-2)
  (SETF (GET 'C-2 :COMPUTATION) T))
T

但是,当我的代码组织在ADSF系统中,以便c-1c-2在文件中,而c-3在另一个文件中时,我看到为c-2生成的代码实际上并不是包装c-1

代码语言:javascript
复制
(PROG1
    (DEFUN C-2 ()
      (DECLARE (OPTIMIZE (SAFETY 3) (SPACE 3)))
      (C-1)
      (FORMAT T "~&Compute something 2"))
  (EXPORT 'C-2)
  (SETF (GET 'C-2 :COMPUTATION) T))

对于SBCL和CCL64,这似乎是正确的。

我猜想这是由宏扩展和加载/编译逻辑的交互造成的,但我对Lisp的这些方面不够精通,无法解释和解决不想要的行为。

给定下面的代码,我如何将其组织在一个ADSF模块中,以便在一个文件中定义C1和C-2,在另一个文件中定义C-3,从而使C-2的宏扩展具有(SUPERVISE-COMPUTATION (C-1))形式,而不是在加载系统时只使用(C-1)。(同样,在REPL中计算下面的表单不会显示问题。)

代码语言:javascript
复制
(defmacro supervise-computation (&body body-forms)
  "Supervise the computation BODY-FORMS."
  `(progn
     (format t "~&---> Computation starts")
     ,@body-forms
     (format t "~&---> Computation stops")))

(defun define-computation/wrap-computation-forms (body-forms)
  "Walks through BODY-FORMS and wrap computation forms in a fixture."
  (labels
      ((is-funcall-p (form)
         (when (and (listp form) (not (null form)) (symbolp (first form)) (listp (rest form)))
           (case (first form)
             ((funcall apply)
              (second form))
             (t (first form)))))
       (is-computation-form-p (form)
         (get (is-funcall-p form) :computation))
       (wrap-computation-forms (form)
         (cond
       ((is-computation-form-p form)
        `(supervise-computation ,form))
           ((is-funcall-p form)
            (cons (first form) (mapcar #'wrap-computation-forms (rest form))))
           (t
        form))))
    (mapcar #'wrap-computation-forms body-forms)))

(defmacro define-computation (computation-name computation-args &body body)
  `(prog1
       (defun ,computation-name ,computation-args
     (declare (optimize (safety 3) (space 3)))
     ,@(define-computation/wrap-computation-forms body))
     (export (quote ,computation-name))
     (setf (get (quote ,computation-name) :computation) t)))

(define-computation c-1 ()
  (format t "~&Compute something 1"))

(define-computation c-2 ()
  (c-1)
  (format t "~&Compute something 2"))

(define-computation c-3 ()
  (c-2)
  (format t "~&Compute something 3"))
EN

回答 1

Stack Overflow用户

发布于 2022-04-02 04:39:14

睡在上面,看看别人的代码(谢谢你的回指),我可以想出一个更好的方法来编写宏

代码语言:javascript
复制
(defmacro define-computation (computation-name computation-args &body body)
  (setf (get computation-name :computation) t)
  `(prog1
      (defun ,computation-name ,computation-args
       (declare (optimize (safety 3) (space 3)))
       ,@(define-computation/wrap-computation-forms body)
      (export (quote ,computation-name))))

这将确保在宏计算时设置属性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71713291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档