Macros 我的第一个Lisp宏;漏水吗?

Macros 我的第一个Lisp宏;漏水吗?,macros,lisp,Macros,Lisp,我一直在练习,并决定编写一个宏来确定一个数字是否是另一个数字的倍数: (defmacro multp(值因子) `(=(rem,值,系数)0)) 以便: (multp 40 10) 计算结果为true,而 (multp 40 13) 不 问题是这个宏是否以某种方式存在?这也是“好”的口齿不清吗?是否已经有我可以使用的现有函数/宏?Siebel给出了可能的泄漏源的详细分析(无论如何,对于简单的情况),这里没有任何泄漏源。value和factor仅按顺序评估一次,并且rem没有任何副作用 但这不是一

我一直在练习,并决定编写一个宏来确定一个数字是否是另一个数字的倍数:

(defmacro multp(值因子)
`(=(rem,值,系数)0))

以便:
(multp 40 10)
计算结果为true,而
(multp 40 13)


问题是这个宏是否以某种方式存在?这也是“好”的口齿不清吗?是否已经有我可以使用的现有函数/宏?

Siebel给出了可能的泄漏源的详细分析(无论如何,对于简单的情况),这里没有任何泄漏源。
value
factor
仅按顺序评估一次,并且
rem
没有任何副作用

但这不是一个好的Lisp,因为在这种情况下没有理由使用宏。函数

(defun multp (value factor)
  (zerop (rem value factor)))

在所有实际用途中都是相同的。(注意使用了
zerop
。我认为在这种情况下它会让事情变得更清楚,但是在需要强调的情况下,如果测试的值不是零,那么它可能仍然有意义,
(=…0)
可能更好)

我觉得你的宏看起来不错。我不知道什么是泄漏宏,但您的宏非常简单,不需要任何gensym。至于这是否是“好的”Lisp,我的经验法则是仅在函数不起作用时才使用宏,在这种情况下,可以使用函数代替宏。但是,如果此解决方案适合您,则没有理由不使用它。

原则上,用户可以这样做:

(flet ((= (&rest args) nil))
  (multp 40 10))
这将评估为零。。。除了ANSI CL规定重新绑定大多数标准符号是非法的,包括CL:=,所以在这种特殊情况下,您是安全的


当然,一般来说,您应该注意引用不可转换性(从宏展开的上下文中捕获标识符)和宏不卫生性(将标识符泄漏到展开的代码中)。

否,宏的“词法闭包”中引入的符号不会释放到外部

请注意,泄漏不一定是坏事,即使意外泄漏几乎总是坏事。对于我参与的一个项目,我发现类似的宏非常有用:

(defmacro ana-and (&rest forms)
  (loop for form in (reverse forms)
        for completion = form then `(let ((it ,form))
                                      (when it
                                       ,completion))
        finally (return completion)))

这使我能够“短路”需要按顺序完成的事情,并从顺序中的先前调用中继承参数(返回NIL表示失败)。这段代码所处的特定环境是一个手工编写的配置文件解析器,该配置文件的语法拼凑得足够好,因此使用解析器生成器编写一个合适的解析器比手工编写更费劲。

非常感谢。那么,对于作为练习而创建的简单合理宏的要求,您有什么想法吗?