Common Lisp (SBCL) 中的素数宏
Primality Macro in Common Lisp (SBCL)
这是我编写的用于测试素数的宏:
(defmacro primep (num)
`(not (or ,@(loop for p in *primes* collecting `(= (mod ,num ,p) 0)))))
*primes*
是一个动态变量,它包含到目前为止生成的素数列表(上下文是一个 'next prime generator' 函数)。以下是一些 eval-ed 语句的结果:
(let ((*primes* (list 2 3)))
(primep 6))
-> T
(let ((*primes* (list 2 3)))
(macroexpand-1 '(primep 6))
-> (NOT (OR (= (MOD 6 2) 0) (= (MOD 6 3) 0)))
-> T
(NOT (OR (= (MOD 6 2) 0) (= (MOD 6 3) 0)))
-> NIL
这是怎么回事?
你应该为此使用一个函数。宏用于生成代码。这里的问题是 *PRIMES*
的 LET
绑定发生在 运行 时间,而不是在宏扩展期间。
你的函数代码看起来像这样。
(defparameter *primes* (list))
(defun primep (num)
(not (loop for p in *primes* thereis (zerop (mod num p)))))
(let ((*primes* (list 2 3)))
(primep 6))
;=> NIL
(let ((*primes* (list 2 3)))
(primep 7))
;=> T
这是我编写的用于测试素数的宏:
(defmacro primep (num)
`(not (or ,@(loop for p in *primes* collecting `(= (mod ,num ,p) 0)))))
*primes*
是一个动态变量,它包含到目前为止生成的素数列表(上下文是一个 'next prime generator' 函数)。以下是一些 eval-ed 语句的结果:
(let ((*primes* (list 2 3)))
(primep 6))
-> T
(let ((*primes* (list 2 3)))
(macroexpand-1 '(primep 6))
-> (NOT (OR (= (MOD 6 2) 0) (= (MOD 6 3) 0)))
-> T
(NOT (OR (= (MOD 6 2) 0) (= (MOD 6 3) 0)))
-> NIL
这是怎么回事?
你应该为此使用一个函数。宏用于生成代码。这里的问题是 *PRIMES*
的 LET
绑定发生在 运行 时间,而不是在宏扩展期间。
你的函数代码看起来像这样。
(defparameter *primes* (list))
(defun primep (num)
(not (loop for p in *primes* thereis (zerop (mod num p)))))
(let ((*primes* (list 2 3)))
(primep 6))
;=> NIL
(let ((*primes* (list 2 3)))
(primep 7))
;=> T