学习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
.
用DO*
而不是DO
.
DO
在初始化一个范围绑定,他们是不是还没有看到. DO*
初始化的范围内,他们的绑定是可见的.
在这种特殊情况下var
需要引用其他绑定loop-start
.