使用宏时,每次迭代后参数递增

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用宏时,每次迭代后参数递增相关的知识,希望对你有一定的参考价值。

所以我有这个宏(基本上是for循环):

(defmacro for ((parameter start-value end-value &optional (step 1)) &body e)
  (let ((func-name (gensym))
        (end (gensym)))
    `(labels ((,func-name (,parameter ,end)
                  (if (<= ,parameter ,end) 
                      (progn ,@e 
                             (,func-name (+ ,parameter ,step) ,end)))))
       (,func-name ,start-value ,end-value))))

我想用它来测试它:

(print (let ((j 0) (k 1))
      (for (i 1 10 (incf k)) (print i))))

我现在得到的是:

1, 3, 6, 10, NIL.

这意味着我的步骤在每次迭代后递增,但我希望它在此输出的开头只增加一次:

1, 3, 5, 7, 9, NIL.

我的宏有什么问题,我该怎么办?

答案

您需要计算循环外的步长值:

CL-USER 12 > (defmacro for ((parameter start-value end-value
                             &optional (step 1))
                            &body e)
               (let ((func-name (gensym))
                     (step-name (gensym))
                     (end (gensym)))
                 `(labels ((,func-name (,parameter ,end ,step-name)
                             (when (<= ,parameter ,end) 
                               ,@e 
                               (,func-name (+ ,parameter ,step-name)
                                           ,end
                                           ,step-name))))
                    (,func-name ,start-value ,end-value ,step))))
FOR

CL-USER 13 > (pprint (macroexpand-1 '(for (i 1 10 (incf k)) (print i))))

(LABELS ((#:G954 (I #:G956 #:G955)
           (WHEN (<= I #:G956) (PRINT I) (#:G954 (+ I #:G955) #:G956 #:G955))))
  (#:G954 1 10 (INCF K)))

CL-USER 14 > (let ((j 0) (k 1))
               (for (i 1 10 (incf k))
                 (print i)))

1 
3 
5 
7 
9 
NIL

如果您不想一直传递步长值,则需要外部LET绑定其值。

注意:一些Lisp实现(许多解释器和一些编译器)不支持TCO(尾调用优化)。

以上是关于使用宏时,每次迭代后参数递增的主要内容,如果未能解决你的问题,请参考以下文章

调用宏时参数过多

每次重启后都会添加片段(Android)

如何使用 ViewPager 显示相同的片段,但每次加载不同的数据?

每次创建新对象时迭代 NSManagedObject 的属性

在每次迭代中重新声明变量是不是比在每次迭代后重置它们更快?

每次迭代后存储矩阵