Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 如何为dolist样式的宏生成迭代驱动程序?_Loops_Common Lisp - Fatal编程技术网

Loops 如何为dolist样式的宏生成迭代驱动程序?

Loops 如何为dolist样式的宏生成迭代驱动程序?,loops,common-lisp,Loops,Common Lisp,假设我有这样一个dolist风格的宏: (defmacro do-factorials (var n &body body) (let ((i (gensym))) `(let ((,var 1)) (dotimes (,i ,n) (setf ,var (* ,var (1+ ,i))) ,@body))))) 我想为库创建一个驱动程序,它允许我执行以下操作: (iter (for x in-factorials 10) (

假设我有这样一个dolist风格的宏:

(defmacro do-factorials (var n &body body) 
  (let ((i (gensym)))
    `(let ((,var 1))
       (dotimes (,i ,n)
     (setf ,var (* ,var (1+ ,i)))
     ,@body)))))
我想为库创建一个驱动程序,它允许我执行以下操作:

(iter (for x in-factorials 10)
      (for y in '(a b c d e))
      (format t "~a ~a~%" x y))
然而,据我所知,iter宏只能用扩展成其他迭代子句的子句进行扩展,而为此,我需要能够在do阶乘中包装其他代码。是否有可靠的方法来实现这一点

哈希表内和包内的实现与我的因式分解的工作方式类似,但它们是使用内部函数和宏实现的,我不希望使用未导出或记录的符号


对于这个简单的例子,可以很容易地用iterate重写它,但一般来说,这并不总是可行的。例如,“做任何事”宏可能来自第三方库。

我没有真正使用cl:iterate,但根据中的文档和示例,我提出了以下建议:

(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用户),我不确定对于非序列的东西是否有必要:

我们仍然缺少一件事:序列关键字。我们可以 通过写作,你可以很容易地理解它们

(defmacro-driver (FOR var IN-WHOLE-VECTOR v &sequence)
  …)
我们现在可以引用from、to、by等参数,这些参数包含 对应关键字的值,如果关键字为空,则为nil 没有供应。为这些关键字实现正确的代码是 笨重但不困难;这只是一个练习。但之前 开始时,请参阅下面的DEF子句序列以了解更简单的方法

我不确定这是否符合你说的意思:

对于这个简单的例子,可以很容易地用iterate重写它,但是, 一般来说,这并不总是可行的。例如,用户可以做任何事情 宏可以来自第三方库

通常,宏
do xxx
不一定公开其迭代技术,这意味着您无法将其实现合并到迭代中。我真的看不到解决这个问题的方法,所以我认为您可能需要根据cl:iterate重写其中的一些内容。但是,我没有使用文档中没有描述的任何东西(而且我对cl:iterate是完全陌生的),因此我认为您在以下方面是安全的:

在哈希表和包中的实现类似于 我的因式分解可以工作,但它们是使用内部 函数和宏,我不希望使用 未导出或记录


我只是举个例子。也许更好的例子是第三方hashset库,其中循环的唯一机制是使用
do hashset
。在iterate中,似乎没有任何方法可以为所述hashset创建驱动程序。一个可能的解决方案是将do hashet与cl cont结合起来,但是我需要将主体包装在宏中,我不知道如何在驱动程序定义中执行。@Thayne。除非现有的迭代宏公开其实现,或者您可以在迭代之间以某种方式“暂停”,否则您需要提前进行迭代并收集元素,或者重新实现迭代。