为什么习惯上在基于Lisp的语言中将许多右括号放在一行上?

Vi.*_*Vi. 35 lisp coding-style clojure parentheses

通常代码如下所示:

(one-thing
    (another-thing arg1 (f arg5 r))
    (another-thing arg1 (f arg5 r)))
Run Code Online (Sandbox Code Playgroud)

为什么不喜欢这个?:

(one-thing
    (another-thing arg1 (f arg5 r))
    (another-thing arg1 (f arg5 r))
)
Run Code Online (Sandbox Code Playgroud)

它允许更容易地添加和删除"另一个东西"行(不删除和重新添加尾部右括号).你也可以对那个单独的右括号(例如";循环结束")发表一些评论.

当我使用第二种风格的代码与使用第一种风格的现有代码混合时有多糟糕?

Gar*_*ees 46

在Lisp和其他使用S表达式语法的语言中,括号主要是为了编译器的利益,而布局和缩进(编译器忽略它们)是为了程序员的利益.

因此,没有必要在它们自己的行上放置右括号:精心选择的换行符和缩进将足以使结构清晰.

例如,

(defun clone-indirect-buffer-other-window (newname display-flag &optional norecord)
  "Like `clone-indirect-buffer' but display in another window."
  (interactive
   (progn
     (if (get major-mode 'no-clone-indirect)
         (error "Cannot indirectly clone a buffer in %s mode" mode-name))
     (list (if current-prefix-arg
               (read-buffer "Name of indirect buffer: " (current-buffer)))
           t)))
  (let ((pop-up-windows t))
    (clone-indirect-buffer newname display-flag norecord)))
Run Code Online (Sandbox Code Playgroud)

从缩进中可以清楚地看到(对于经验丰富的Lisp程序员).通过将一些右括号放到新行上,不会添加任何内容:

(defun clone-indirect-buffer-other-window (newname display-flag &optional norecord)
  "Like `clone-indirect-buffer' but display in another window."
  (interactive
   (progn
     (if (get major-mode 'no-clone-indirect)
         (error "Cannot indirectly clone a buffer in %s mode" mode-name)
       )
     (list (if current-prefix-arg
               (read-buffer "Name of indirect buffer: " (current-buffer))
             )
           t)
     )
   )
  (let ((pop-up-windows t))
    (clone-indirect-buffer newname display-flag norecord)
    )
  )
Run Code Online (Sandbox Code Playgroud)

我应该补充说,几乎所有Lisp程序员都使用一个显示匹配括号的编辑器,执行自动缩进,并提供一个用户界面,用于直接使用平衡表达式.例如,在Emacs中,用于M-(插入新表达式,M-)用于移动超过当前表达式的末尾,C-M-k用于删除点之后的表达式,依此类推.

因此,Lisp程序员永远不必手动计算括号,以便找出哪些匹配.


Taylor R. Campbell雄辩地表达了这个理由:

实际的括号字符只是词汇标记,应赋予其不重要的意义.Lisp程序员不会单独检查括号,或者,Azathoth禁止计数括号; 相反,他们会查看程序中表达的更高级别的结构,尤其是缩进所呈现的结构.Lisp不是要编写一系列串行指令; 它是通过对零件进行求和来构建复杂的结构.部件中复杂结构的组合是Lisp程序的重点,从Lisp代码中可以很容易地看出它.随意放置关于演示文稿的括号对于Lisp程序员来说是不和谐的,否则他们甚至都不会在大多数情况下看到它们.

  • 事实上,人们避免将自己的问题放在自己的线上的一个很好的理由是它使得它们更容易计算,并且计算parens是人类应该做的事情. (3认同)
  • “并提供一个直接使用平衡表达式的用户界面” - 这部分尚未在我的 Vim 中配置,这是我考虑将一些右括号放在单独的行上的主要原因。 (2认同)

tel*_*ent 29

这里有两点要点:

  1. 公约本身很重要.坚持包裹的parens意味着你的代码更容易被其他lisp程序员阅读,如果你采用这种风格,你也会开发练习阅读他们的

  2. )s 分割到自己的线上的优点实际上并不是大多数lispers眼中的优点.如果你使用的是一个不错的编辑器,那么它将具有理解平衡表达式,移动它们,剪切,粘贴,移调等的命令.所以你不需要

    )  ; end of the loop
    
    Run Code Online (Sandbox Code Playgroud)

    在lisp中不仅仅是你需要的

    # end of the loop
    
    Run Code Online (Sandbox Code Playgroud)

    在像Python这样的空白敏感语言中

参见例如http://www.gnu.org/software/emacs/manual/html_node/emacs/Expressions.html

  • 他们往往不是Lisp程序员.但是没有多少"ed"和"edlin"用户离开了,是吗?Vi(m)用户,请查看http://stackoverflow.com/questions/94792/using-vim-for-lisp-development (9认同)
  • 我不能说我同意理由#1,或者它首先列出.它听起来像Lisp程序员使用这种风格主要是因为所有其他Lisp程序员都这样做.:-)#2实际上是真正的原因:它节省了大量的空间,并且(很少)更难以")""在同一条线上,我们通过将这个功能添加到我们的编辑器(在部分因为Lisp很容易解析). (2认同)
  • "公约本身很重要." ...那么也许我们都应该用Java编程.你没有说过对传统风格的任何辩护,你只是说它是传统的,传统的喜欢它......并且它需要一个特殊的编辑器来处理它(反对它的一点). (2认同)

fog*_*gus 11

简短回答:偏离公认的标准只会疏远潜在的贡献者.没有一种风格比另一种更好.

答案很长:http://blog.fogus.me/2010/08/30/community-standards/

  • 我不认为这回答了这个问题.坚持习俗可能是有利的,但这并不能说明为什么有人会选择这种特殊的习俗.曾几何时,有人必须首先以这种方式写作,并且(通过共识,权威或其他原因)使其成为"公认的标准". (4认同)