当前位置:  开发笔记 > 编程语言 > 正文

使用gensym的以下Common Lisp宏有什么问题?

如何解决《使用gensym的以下CommonLisp宏有什么问题?》经验,为你挑选了1个好方法。

学习Common Lisp(使用GNU CLISP 2.43)..所以可能是一个noob错误.示例是'x和y之间的'打印素数'

(defun is-prime (n)
  (if (< n 2) (return-from is-prime NIL))

  (do ((i 2 (1+ i)))
      ((= i n) T)
    (if (= (mod n i) 0) 
        (return NIL))))

(defun next-prime-after (n)
  (do ((i (1+ n) (1+ i)))
      ((is-prime i) i)))

(defmacro do-primes-v2 ((var start end) &body body)
  `(do ((,var (if (is-prime ,start)
                  ,start
                  (next-prime-after ,start))
              (next-prime-after ,var)))
       ((> ,var ,end))
     ,@body))

(defmacro do-primes-v3 ((var start end) &body body)
  (let ((loop-start (gensym))
        (loop-end (gensym))) 
    `(do ((,loop-start ,start)
          (,loop-end ,end)
          (,var (if (is-prime ,loop-start)
                    ,loop-start
                    (next-prime-after ,loop-start))
                (next-prime-after ,var)))
         ((> ,var ,loop-end))
       ,@body )))

do-primes-v2完美运行.

[13]> (do-primes-v2 (p 10 25) (format t "~d " p))
11 13 17 19 23

接下来我尝试使用gensym来避免在宏扩展中命名冲突 - do-primes-v3.但是我坚持了

*** - EVAL: variable #:G3498 has no value

尝试使用宏扩展来查看我是否可以发现错误,但我不能.

[16]> (macroexpand-1 `(do-primes-v3 (p 10 25) (format t "~d " p)))
(DO
 ((#:G3502 10) (#:G3503 25)
  (P (IF (IS-PRIME #:G3502) #:G3502 (NEXT-PRIME-AFTER #:G3502))
     (NEXT-PRIME-AFTER P)))
 ((> P #:G3503)) (FORMAT T "~d " P)) ;

kmkaplan.. 5

DO*而不是DO.

DO在初始化一个范围绑定,他们是不是还没有看到. DO*初始化的范围内,他们的绑定可见的.

在这种特殊情况下var需要引用其他绑定loop-start.



1> kmkaplan..:

DO*而不是DO.

DO在初始化一个范围绑定,他们是不是还没有看到. DO*初始化的范围内,他们的绑定可见的.

在这种特殊情况下var需要引用其他绑定loop-start.

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有