SBCL 编译器诊断消息(缺少 "when",没有正文)

SBCL Compiler Diagnostic Messages (missing with a "when" with no body)

我最近偶然在处理 when 语句的一个函数中遇到了一个潜在的编码错误。简化的释义可能如下所示:

(defparameter a 0)

(when (or (= a 0)
          (= a 1)
  (* a a)))

问题是括号放错了,原来是

(when (or (= a 0)
          (= a 1)
          (* a a)))

在这种情况下,编译器生成样式警告或注释不是很有用吗?在我看来,when 语句的含义通常意味着条件和主体,即使主体是严格可选的。当然,印刷漂亮的人会在编辑器中捕捉到这一点,但我是从别处复制的。 SBCL 不检查此类错误的原因是什么?

a print pretty would have caught this in the editor

为了讨论选项,我知道:

  • trivial-formatter 将格式化源代码。

    (trivial-formatter:fmt :your-system :取代)

  • cl-indentify 缩进源代码。有一个命令行实用程序。试了一次还不错,就是和E​​macs的缩进不一样,所以很烦。

    $cl-indentifybar.lisp

它链接到 lispindent,但我对其结果不太满意。

但是,最好的办法不仅是格式化代码并 re-read 我们自己,而且

运行 检查一组规则以警告代码异味

这就是 lisp-critic 的提议。它可以批评一个函数或一个文件。然而:

  • (edit) 它并没有真正与 Slime 集成,我们必须批评一个函数或整个文件。
    • 如果您喜欢冒险,请查看我的实用程序 here。这可能是一种更简单的方法来测试您在 REPL 中输入的片段。
  • 它没有关于 when 没有 body 的规则(我们可以很容易地添加它)

如果 运行 发现代码异味,则最好以错误状态代码失败。同样,我在测试版中的一个小项目试图做到这一点,请参阅 here。它现在没有太多规则,但我只是为此推了一个检查。您可以调用脚本:

$colisper.sh tests/playground.lisp 

显示错误(但默认不写in-place):

 |;; when with no body
 |(when (or (= a 0)
 |          (= a 1)
!|     (* a a))
!|  (error "colisper found a 'when' with a missing body. (we should error the script without this rewrite!)"))

和 returns 带有退出代码,因此我们可以在 git 挂钩或 CI 管道上使用它。

问题是,如果 human(when x)(或任何扩展成 (if x (progn) nil))这可能是一个错误,但是当一个 program 写的它很可能不是:它可能只是一些边缘情况,程序还不够聪明,无法完全优化。而且编译器处理的大量代码是由程序编写的,而不是人类编写的。