特定于SBCL的声明

rwa*_*ace 2 sbcl common-lisp

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

(declaim (sb-ext:muffle-conditions style-warning))
Run Code Online (Sandbox Code Playgroud)

缺点是CCL出于显而易见的原因,对包含上述内容的程序进行了限制.我尝试用条件解决这个问题:

(#+sbcl (declaim (sb-ext:muffle-conditions style-warning)))
Run Code Online (Sandbox Code Playgroud)

但现在SBCL不高兴:"非法打电话".

你如何将这样的声明放入便携式程序?

cor*_*ump 6

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

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

例如,在文件中#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)))
Run Code Online (Sandbox Code Playgroud)

不要评估文件中的任何内容; 改为做:

(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
Run Code Online (Sandbox Code Playgroud)

没有警告.然后,您可以(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))))
Run Code Online (Sandbox Code Playgroud)

评估整个块显示没有警告*EVALUATOR-MODE*同时:COMPILE:INTERPRET.

当您逐个评估每个表达式(或者可能是另一个表达式之后的一个区域)时,您所见证的情况会发生.在那里,编译器无法知道该函数已经存在.沉默警告是更糟糕的选择,因为您实际上可能犯了错误.

如果你事先知道的功能存在,但不是在你的编译单元(也许它只是在运行时所定义的),则可以朗诵这一事实,具体如下:

(declaim (ftype function my-function))
Run Code Online (Sandbox Code Playgroud)

上面说的my-function必须假设是fbound一个类型的对象function.您还可以通过改进您声称的功能来提供更多信息:

(declaim (ftype (function (number) (values string &optional)) num-to-string))
Run Code Online (Sandbox Code Playgroud)

...对于接受数字并且只返回一个值的函数,一个字符串.

(declaim (ftype (function () nil) forever-loop))
Run Code Online (Sandbox Code Playgroud)

...对于一个不接受任何东西并且永远不会返回值的函数(循环或发出错误信号).


Dir*_*irk 5

省略外面的括号:

#+sbcl (declaim (sb-ext:muffle-conditions style-warning))
Run Code Online (Sandbox Code Playgroud)

正如您所使用的那样declaim,我假设声明出现在编译单元的顶层.如果您需要对多个顶级语句进行分组,则可以使用a来包装它们progn(这不会更改"顶级"-ness).

SBCL抱怨的原因是它的读者读到了

((declaim (sb-ext:muffle-conditions style-warning)))
Run Code Online (Sandbox Code Playgroud)

(因为该:SBCL功能存在),这只是一个语法错误.CCL没有抱怨,因为它的读者读到了

()
Run Code Online (Sandbox Code Playgroud)

这只是另一种拼写方式nil.