【问题标题】:Primality Macro in Common Lisp (SBCL)Common Lisp (SBCL) 中的素数宏
【发布时间】:2016-10-27 22:26:58
【问题描述】:

这是我编写的用于测试素数的宏:

(defmacro primep (num)
  `(not (or ,@(loop for p in *primes* collecting `(= (mod ,num ,p) 0)))))

*primes* 是一个动态变量,其中包含到目前为止生成的素数列表(上下文是“下一个素数生成器”函数)。以下是一些 eval 语句的结果:

(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 绑定发生在运行时,而不是在宏扩展期间。
  • @jkiiski 如何使用函数生成所有这些(= (mod ... 语句?我认为这就是宏的用途(我刚刚开始学习 Common Lisp)。
  • 您不需要生成它们。像使用任何其他语言一样使用循环。
  • @jkiiski 好的,谢谢。我会试试的。你可以添加这个(也许是一个例子)作为答案让我接受吗?

标签: macros lisp common-lisp sbcl


【解决方案1】:

你应该为此使用一个函数。宏用于生成代码。这里的问题是*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

【讨论】:

  • 使用loopthereis 比使用dolist 有什么优势吗?
  • 没有真正的优势,但LOOP 更易于使用。使用DOLIST,您必须自己编写退出循环。
猜你喜欢
  • 1970-01-01
  • 2019-12-28
  • 1970-01-01
  • 2017-02-27
  • 2015-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多