假设我有这样的dolist风格宏:
(defmacro do-factorials (var n &body body)
(let ((i (gensym)))
`(let ((,var 1))
(dotimes (,i ,n)
(setf ,var (* ,var (1+ ,i)))
,@body)))))
我想为iterate库创建一个驱动程序,这可以让我做这样的事情:
(iter (for x in-factorials 10)
(for y in '(a b c d e))
(format t "~a ~a~%" x y))
但是,据我所知,iter宏只能扩展为扩展到其他iterate子句的子句,而为此,我需要能够将其他代码包装在do-factorials中。无论如何以可靠的方式做到这一点?
in-hashtable和in-package工作的实现类似于我的因子如何工作,但它们是使用内部函数和宏实现的,我宁愿不使用未导出或记录的符号。
对于这个简单的情况,用iterate重写它很容易,但是,一般来说,这并不总是可行的。例如,do-whatever宏可以来自第三方库。
答案 0 :(得分:1)
我还没有真正使用过cl:iterate,但根据7.2 Writing Drivers中的文档和示例,我想出了这个:
(defmacro-driver (FOR var IN-FACTORIALS n)
"All the factorials from 1! to n!."
(let ((end (gensym))
(fact (gensym))
(index (gensym))
(kwd (if generate 'generate 'for)))
`(progn
(with ,end = ,n)
(with ,fact = 1)
(with ,index = 0)
(,kwd ,var next (progn (incf ,index)
(if (> ,index ,end) (terminate))
(setf ,fact (* ,fact ,index)))))))
在评估完之后,我可以运行您展示的代码:
CL-USER> (iter (for x in-factorials 10)
(for y in '(a b c d e))
(format t "~a ~a~%" x y))
1 A
2 B
6 C
24 D
120 E
NIL
根据文档,你仍然可能想要处理&sequence
的东西,但是(不是cl:iterate用户),我不确定是否有必要对于不是序列的东西:
我们仍然缺少一件事:& sequence关键字。我们可以得到 他们很容易写,
(defmacro-driver (FOR var IN-WHOLE-VECTOR v &sequence) …)
我们现在可以参考包含其中一个的参数from,to,by等 相应关键字的值,如果关键字为,则为nil 不提供。为这些关键字实现正确的代码是 繁琐而不困难;它留作练习。但之前 你开始吧,请参阅下面的defclause-sequence以获得更简单的方法。
当你说:
时,我不确定这是否属于你的意思对于这个简单的情况,用iterate重写它很容易,但是, 总的来说,这并不总是可行的。例如,做什么 宏可以来自第三方库。
通常,宏do-xxx
不一定会暴露其迭代技术,这意味着您无法将其实现应用于迭代。我真的没有看到解决方法,所以我认为你可能不得不用cl:iterate重写一些。但是,我没有使用文档中没有描述的任何内容(我对cl:iterate完全不熟悉),所以我认为你是安全的:
in-hashtable和in-package工作的实现类似于如何实现 我的因子可以工作,但它们是使用内部实现的 函数和宏,我宁愿不使用符号 不会导出或记录。