38

一位花时间评论我关于 Clojure/LISP 语法的其他问题的人指出,我没有以标准 LISP 方式编写示例代码。所以他很友好地重写了代码片段,这是一个很大的帮助。但它在我的脑海中提出了另一个问题。为什么会这样:

(if (= a something)
  (if (= b otherthing)
    (foo)))

这是标准 LISP 格式比这种形式更可取:

(if (= a something)
  (if (= b otherthing)
    (foo)
  )
)

由于我的 C++ 开发背景,这就是我天真地格式化此代码的方式。我想知道后一种格式是否有任何好处,或者它只是一个根深蒂固的标准(如 QWERTY 键盘)。我并不是要争论——我很难理解为什么第一种形式更可取。第二种形式帮助我更容易地查看代码结构。

4

5 回答 5

40

额外行的右括号并不能真正帮助查看代码的结构,因为您可以从缩进级别获得相同的信息。然而,第二种形式占用了几乎两倍的行数,迫使您在阅读代码时更频繁地滚动。

如果您需要更仔细地检查嵌套括号,突出显示匹配括号的编辑器将为您提供帮助。当匹配的括号不是太远时,这也会更容易。

如果表达式太长且太复杂而难以阅读,这也可能表明您应该将部分功能提取到单独的函数中。

于 2009-02-12T14:35:52.353 回答
37

Lisp 代码的缩进方式有点像 Python 中的重要空格,除了它当然是可选的。基本的经验法则是,如果项目不在同一行上,则将列表中的项目垂直放置在另一个之下。

(a (b (c (d e)
         (f g))
      (h i j))
   (k l m n))

甚至不用看括号,你就可以看到(d e)and(f g)是 的参数c(c (d e) (f g))and(h i j)是 的参数b(b (c (d e) (f g)) (h i j))and(k l m n)是 的参数a

对于您的示例,它应该更正确地格式化如下:

(if (= a something)
    (if (= b otherthing)
        (foo)))

    ^   ^
  notice how they line up

现在缩进的级别变得有意义,您不再需要依靠平衡括号来获取该信息,并且由于将它们与结束语句放在同一行更紧凑,这就是 lispers 所做的。当然,Lisp 代码不需要以这种方式格式化,但它是人们使用并且可以依赖的相当标准的约定。

于 2009-02-12T14:24:03.083 回答
3

简单的答案是你的方式不是 Lisp 的漂亮打印机做事的方式。拥有一个真正的格式对代码来说总是一件好事,而 pprint 宏为您提供了语言中内置的格式。

当然,由于存在 pprint 宏,因此您不必严格遵循标准代码格式,因为人们可以通过 pprint 运行您的代码并获得他们习惯的内容。然而,由于其他人都使用 pprint,或者手动近似它,如果你不这样做,你将很难阅读代码,而且你没有一个简单的宏可以将他们的代码变成你喜欢的格式。

于 2009-02-23T15:55:17.380 回答
1

您可以使用包 Sreafctor: Homepage重新格式化 Lisp 代码。

一些演示:

可用命令:

  • srefactor-lisp-format-buffer: 格式化整个缓冲区
  • srefactor-lisp-format-defun: 格式化当前 defun 光标所在的位置
  • srefactor-lisp-format-sexp: 格式化当前 sexp 光标所在的位置。
  • srefactor-lisp-one-line:将当前同级别的sexp变成一行;使用前缀参数,递归地将所有内部性别转换为一行。

格式化命令也可用于 Common Lisp 和 Scheme。

如果有任何问题,请提交问题报告,我将很乐意修复它。

于 2015-04-08T10:12:02.510 回答
0

当你有 10 个括号要关闭时,它会变得非常笨重。

当我以前编写 Lisp 时,我在右括号之间留了一个空格,以便在同一行和其余的左括号之间留一个空格,以简化计数,如下所示:

(如果(=某事)
  (如果(= b 其他)
    (富)))

我想这些天不再需要了,因为编辑更有帮助。

于 2009-02-12T14:20:58.287 回答