【问题标题】:SBCL-specific declaimSBCL 特定声明
【发布时间】:2018-09-12 17:16:27
【问题描述】:

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

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

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

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

但现在 SBCL 不高兴:“非法函数调用”。

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

【问题讨论】:

    标签: common-lisp sbcl


    【解决方案1】:

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

    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)))
    

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

    (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 (ftype function my-function))
    

    上面说my-function 必须假定为fboundfunction 类型的对象。您还可以通过完善您声称的功能类型来提供更多信息:

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

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

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

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

    【讨论】:

      【解决方案2】:

      省略外面的一对括号:

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

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

      SBCL 确实抱怨的原因是,它的 读者阅读了

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

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

      ()
      

      这只是nil 的另一种拼写方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-19
        • 1970-01-01
        • 2011-03-06
        • 1970-01-01
        • 2023-03-06
        相关资源
        最近更新 更多