调用函数的宏在解释器中有效,在编译器中失败(SBCL + CMUCL) [英] Macro calling a function works in interpreter, fails in compiler (SBCL + CMUCL)

查看:64
本文介绍了调用函数的宏在解释器中有效,在编译器中失败(SBCL + CMUCL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在SO上发布的与宏相关的问题,通过调用函数(这是pastebin中的独立代码):

(defun main ()
  (progn
    (format t "~A~%" (+ 1 2 (* 3 4) (+ 5 (- 8 6))))
    (format t "~A~%" (fast (+ 1 2 (* 3 4) (+ 5 (- 8 6)))))))

这在SBCL和CMUCL下的REPL中都有效:

This works in the REPL, under both SBCL and CMUCL:

$ sbcl
This is SBCL 1.0.52, an implementation of ANSI Common Lisp.
...
* (load "bug.cl")
22
22

$

但是,不幸的是,该代码不再编译:

Unfortunately, however, the code no longer compiles:

$ sbcl
This is SBCL 1.0.52, an implementation of ANSI Common Lisp.
...
* (compile-file "bug.cl")
...
;   during macroexpansion of (FAST (+ 1 2 ...)). Use *BREAK-ON-SIGNALS* to
;   intercept:
;
;    The function COMMON-LISP-USER::CLONE is undefined.

因此,似乎通过在编译时使用宏快速"调用函数("clone","operation-p"),我触发了Lisp编译器中的问题(在CMUCL和SBCL中均已验证).

So it seems that by having my macro "fast" call functions ("clone","operation-p") at compile-time, I trigger issues in Lisp compilers (verified in both CMUCL and SBCL).

关于我在做什么错和/或如何解决此问题的任何想法?

Any ideas on what I am doing wrong and/or how to fix this?

推荐答案

关于您的代码的一些评论.

Some remarks about your code.

  • 一个对象的多个相等测试可以替换为MEMBER

backquote不会执行任何操作.您可以删除它.

backquote with a following comma does nothing. You can just remove that.

您可以通过a)将这些函数移至其他文件并在使用宏之前对其进行编译/加载,以确保宏可使用您的函数,b)使用EVAL-WHEN通知编译器执行以下操作:评估函数的定义,或通过c)将函数作为本地函数添加到宏中

you can ensure that your functions are available for a macro by a) moving these functions to an additional file and compile/load that before use of the macro, by b) using EVAL-WHENto inform the compiler to evaluate the definition of the functions or by c) adding the functions to the macro as local functions

示例:

(defmacro fast (&rest sexpr)
  (labels ((operation-p (x)
             (member x '(+ - * /)))
           (clone (sexpr)
             (if (consp sexpr)
                 (destructuring-bind (head . tail) sexpr
                   (if (operation-p head)
                       `(the fixnum (,head ,@(clone tail)))
                     (cons (clone head) (clone tail))))
               sexpr)))
    (car (clone sexpr))))

请注意,此版本和您的FAST版本都不是完整的代码遍历器.它们仅识别简单的函数调用(而不能识别其他Lisp构造,例如LAMBDA,LET,FLET,LABELS等).

Note that this and your version of FAST are not complete code walkers. They recognize only simple function calls (and not the other Lisp constructs like LAMBDA, LET, FLET, LABELS, etc.).

这篇关于调用函数的宏在解释器中有效,在编译器中失败(SBCL + CMUCL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆