SBCL 特定声明

SBCL-specific declaim

SBCL 生成关于未定义函数的虚假样式警告。 (函数已定义,就在文件的后面。)我想一劳永逸地解决这个问题。幸运的是,有一种方法可以做到这一点:

(declaim (sb-ext:muffle-conditions style-warning))

缺点是 CCL,出于显而易见的原因,拒绝包含上述内容的程序。我尝试用条件解决这个问题:

(#+sbcl (declaim (sb-ext:muffle-conditions style-warning)))

但现在SBCL不开心:"illegal function call".

如何将这样的声明放入可移植程序中?

省略外面的一对括号:

#+sbcl (declaim (sb-ext:muffle-conditions style-warning))

当您使用 declaim 时,我假设声明出现在编译单元的顶层。如果您需要对多个顶级语句进行分组,您可以用 progn 将它们全部包装起来(这不会改变 "top-level"-ness)。

SBCL 抱怨的原因是,它的 reader 读取

((declaim (sb-ext:muffle-conditions style-warning)))

(因为存在 :SBCL 功能),这只是一个语法错误。 CCL不抱怨,因为reader读

()

这只是 nil.

的另一种拼写方式

请注意,虽然现有答案是正确的,但禁用警告并不是一个好的做法。在您的情况下,可能没有必要。

Common Lisp 有一个编译单元的概念,多个定义组合在一起。这让 compiler/interpreter 有机会处理函数之间的交叉引用(例如,解释器可以收集警告并仅保留那些以后找不到的警告)。

例如,在文件 #P"/tmp/foo.pl" 中:

(defun mut-rec-foo (x)
  (when (plusp x)
    (mut-rec-bar (1- x))))

(defun mut-rec-bar (x)
  (print x)
  (mut-rec-foo (1- x)))

不评估文件中的任何内容;而是做:

(compile-file #P"/tmp/foo.pl")

; compiling (DEFUN MUT-REC-FOO ...)
; compiling (DEFUN MUT-REC-BAR ...)

; /tmp/foo.fasl written
; compilation finished in 0:00:00.002

没有警告。然后您可以调用 (load #P"/tmp/foo.fasl") 以在您当前的 lisp 环境中获得定义,而不会出现警告。 通常,ASDF 和扩展名 Quicklisp 使用 COMPILE-FILE,因此只要将文件捆绑到系统中,您的问题就会消失。

您还可以这样做:

(with-compilation-unit ()
  (defun mut-rec-foo/bis (x)
    (when (plusp x)
      (mut-rec-bar/bis (1- x))))

  (defun mut-rec-bar/bis (x)
    (print x)
    (mut-rec-foo/bis (1- x))))

评估整个块不会显示 *EVALUATOR-MODE*:COMPILE:INTERPRET

的警告

当你一个接一个地计算每个表达式(或者一个区域接一个区域)时,你所看到的就会发生。在那里,编译器无法知道函数已经存在。使警告静音是更糟糕的选择,因为您实际上可能犯了错误。

如果你事先知道一个函数 存在,但不在你的编译单元中(也许它只在运行时定义),你可以 declaim那个事实,如下:

(declaim (ftype function my-function))

上面说 my-function 必须被假定为 fboundfunction 类型的对象。您还可以通过细化您声称的函数类型来提供更多信息:

(declaim (ftype (function (number) (values string &optional)) num-to-string))

... 对于接受数字且 return 恰好是一个值(字符串)的函数。

(declaim (ftype (function () nil) forever-loop))

... 对于不接受任何内容且从不接受 return 值(循环或发出错误信号)的函数。