Macros 如何在common lisp中修改此宏以集成循环中的collect?

Macros 如何在common lisp中修改此宏以集成循环中的collect?,macros,common-lisp,sbcl,Macros,Common Lisp,Sbcl,下面有一个宏,它沿着整数中的位进行迭代。我想像这样集成循环的收集功能: (loop for x in '(a b c d e) for y in '(1 2 3 4 5) collect (list x y) ) 我应该如何修改下面的宏来完成上述操作 (defmacro do-bits ((var x) &rest body) "Evaluates [body] forms after binding [var] to each set bit in [x

下面有一个宏,它沿着整数中的位进行迭代。我想像这样集成循环的收集功能:

 (loop for x in '(a b c d e)
      for y in '(1 2 3 4 5)
      collect (list x y) )
我应该如何修改下面的宏来完成上述操作

(defmacro do-bits ((var x) &rest body)
  "Evaluates [body] forms after binding [var] to each set bit in [x]"
  (let ((k (gensym)))
    `(do ((,k ,x (logand ,k (1- ,k))))
         ((= ,k 0))
       (let ((,var (logand ,k (- ,k))))
         ,@body))))

下面是一个简单的宏
和收集器
,它应该可以做到这一点:

(defmacro with-collector ((&optional (collector-name 'collect)) &body body)
  (let ((result (gensym)))
    `(let ((,result (list)))
       (flet ((,collector-name (arg) (push arg ,result)))
         (progn ,@body)
         (when ,result
           (nreverse ,result)))))
默认情况下,它使用名称
collect

(with-collector ()
  (collect 'a)
  (collect 'b)); => (A B)
但如果愿意,您可以使用其他名称(例如,用于嵌套或解决符号冲突)

要将其与宏集成,只需包装
do
表单:

(defmacro do-bits ((var x) &rest body)
  "Evaluates [body] forms after binding [var] to each set bit in [x]"
  (let ((k (gensym)))
    `(with-collector ()
       (do ((,k ,x (logand ,k (1- ,k))))
           ((= ,k 0))
         (let ((,var (logand ,k (- ,k))))
           ,@body)))))
collect
将在正文中提供:

(do-bits (x 255) (collect x))
; => (1 2 4 8 16 32 64 128)
(do-bits (x 256) (collect x))
; => (256)

那么我应该如何将其与我提供的宏集成呢?我认为这样组合宏会起作用:(与收集器()(执行位…)我得到了这个
;捕获样式警告:;不应丢弃NREVERSE的返回值。
当使用没有返回值的do位时。看来我必须归还一些东西,否则就不行了。有办法解决这个问题吗?我在ccl或sbcl中没有看到警告,但我没有使用最新版本的ccl或sbcl。。。在反转结果之前,编辑宏以检查是否累积了任何值。这消除了你的警告吗?一个非常有用的回指宏!
(do-bits (x 255) (collect x))
; => (1 2 4 8 16 32 64 128)
(do-bits (x 256) (collect x))
; => (256)