Coding style Lisp括号

Coding style Lisp括号,coding-style,lisp,Coding Style,Lisp,为什么Lispers的代码格式像示例1中所示,而不是像示例2中所示?对我来说(我想,对于大多数来自不同编程背景而非Lisp的人来说),示例2中显示的格式更易于阅读。Lispers喜欢示例1样式有什么特别的原因吗 样本1 (defun阶乘(n) (如果(节省所有空间似乎是主要原因。如果它几乎同样可读(尤其是一旦你习惯了语法),为什么要使用额外的3行。仅仅是第一个明显的原因:第一种情况下4 LOC,第二种情况下7 LOC 任何了解LISP语法的文本编辑器都会突出显示匹配/不匹配的括号,因此这不是问题

为什么Lispers的代码格式像示例1中所示,而不是像示例2中所示?对我来说(我想,对于大多数来自不同编程背景而非Lisp的人来说),示例2中显示的格式更易于阅读。Lispers喜欢示例1样式有什么特别的原因吗

样本1
(defun阶乘(n)

(如果(节省所有空间似乎是主要原因。如果它几乎同样可读(尤其是一旦你习惯了语法),为什么要使用额外的3行。

仅仅是第一个明显的原因:第一种情况下4 LOC,第二种情况下7 LOC


任何了解LISP语法的文本编辑器都会突出显示匹配/不匹配的括号,因此这不是问题。

使用LISP一段时间后,您不再注意到括号,因此示例二的结尾有一堆不必要的空格。更具体地说,大多数Lisper使用的编辑器都是注意括号并正确关闭表单,因此作为开发人员,您不需要像在C中那样匹配开始括号和结束括号

至于最后一张表格是否应该

(* n (factorial (- n 1)))


这主要取决于个人偏好以及代码中发生了多少事情(在本例中,我更喜欢前者,因为代码中发生的事情太少了).

因为根本不需要排列结束参数。它不会在语义上添加任何内容。为了知道要关闭多少,大多数Lisper都使用了一个好的编辑器,例如Emacs,它可以将结束参数与结束参数相匹配,从而使任务变得简单


在Python中,根本没有结束参数或
end
关键字,Pythonistas也活得很好。

LISP IDE环境倾向于自动平衡括号并基于嵌套级别管理缩进。示例2在这些情况下没有任何优势


在C/FORTRAN/Pascal传统中,您倾向于强调排序而不是嵌套(代码解析树更浅、更宽).End of scope在代码中是一个更重要的事件:因此强调在某种程度上一直是更重要的。

我在使用CakePHP框架及其许多嵌套的
数组()的PHP中遇到了同样的困境
结构,有时5层以上。过了一会儿,我意识到,在右括号上使用OCD只会浪费我宝贵的开发时间,分散我对最终目标的注意力。缩进是格式化最有用的方面。

除了大多数Lisp IDE使用paren匹配之外,a你用来编写任何合理的程序的空间量都是荒谬的!你会从所有的滚动中得到腕管。如果你把所有的右括号都放在自己的行上,一个1000行的程序将接近一百万行代码。在一个小程序中,它可能看起来更漂亮,更容易阅读,但这个想法不可能实现很好。

对于有经验的Lisp用户来说,嵌套级别比查找右括号更重要。将右括号放在他们自己的行中并不能真正帮助嵌套级别

其基本思想是括号直接围绕其内容

(a)
而不是

(a
)
以下是:

(defun foo (bar)
  (foo (bar (baz
              ...
             )
         ...
        )
    ...
   )
 )
vs

编辑Lisp文本时的一个基本思想是,可以通过(双击)括号(或当光标位于表达式内部或括号上时使用键命令)选择列表。然后您可以剪切/复制表达式并将其粘贴到其他函数中的其他位置。下一步是选择其他函数并 重新缩进函数。完成。无需删除或引入新的右括号行。只需粘贴并重新缩进。它正好适合。否则,您将浪费时间格式化代码,或者需要使用某些编辑器工具重新格式化代码(因此,右括号在它们自己的行上。大多数情况下,它会产生额外的工作,并阻碍代码的移动

有一次,有经验的口齿不清者有时会在自己的行中写上结束括号:

(defvar *persons*
   (list (make-person "fred")
         (make-person "jane")
         (make-person "susan")
         ))

此处表示可以添加新人员。将光标直接放在最后一行的第二个右括号之前,按c-o键(开行),添加子句并缩进括号,使其再次对齐。这样就省去了查找右括号的“麻烦”,当所有括号都在一行上闭合时,再按回车键。

因为Lisp程序员查看的是缩进和“形状”,而不是括号。

为什么C程序员编写这样的代码:

((a && b) || (c && d))
而不是

((a && b) || (c && d
             )
)
2不是更容易阅读吗?:)

不过,说真的,这种组合式收尾风格也适用于其他语言

#include <stdlib.h>
#include <stdio.h>

int main(void)
{ int i, j, k;
  for (i = 0; i < 1000; i++)
  { for (j = 0; j < 1000; j++)
    { for (k = 0; k < 1000; k++)
      { if (i * i + j * j == k * k)
        { printf("%d, %d, %d\n", i, j, k); } } } }
  return 0; }
开关:

switch (expr)
{ case '3':
    stmt;
    break;
  case '4':
  { stmt;
    break; } }
结构:

struct foo
{ int x;
  struct bar
  { int y; };
  union u
  { int a, b;
    char c; }; };

你可以考虑不使用()的Lisp变体。在Genyris,它看起来是这样的:

if (cond)
{ stmt;
  stmt; }
else
{ stmt; }
def factorial (n)
  if (< n 2) 1
    * n
      factorial (- n 1)
def阶乘(n)
如果(
这似乎不是一个真正的问题,只是对Lisp的一个判断,但答案是非常明显的(但对非Lisper来说,显然不是!):Lisp中的括号与类C语言中的大括号完全不同——相反,它们与类C语言中的括号完全相同。Lisper通常不会编写代码

(foo bar baz
)
foo(bar, baz
   );
正是出于同样的原因,C程序员通常不会编写

(foo bar baz
)
foo(bar, baz
   );
原因

(if foo
    (bar)
    (baz))
看起来不同于

if (foo) {
   bar();
} else {
   baz();
}

if
有关的更多,而不是括号!

我有一个解释,C程序员在Lispers将所有剩余的右括号放在末尾时遇到问题。在我看来,括号的含义可能是原因。这个解释与其他一些答案重叠并扩展

对于C程序员(或像C一样使用{大括号}的其他语言),Lisp看起来像是使用#| comments |#而不是/*comments*/。并且看起来像Lisp parent
(if foo
    (bar)
    (baz))
if (foo) {
   bar();
} else {
   baz();
}
defun f () nil
Eval( Listener() )
Eval (defun f () nil)
/* REPL expressed in C */
Loop()
{
    Print ( Eval ( Listen () ) );
    Loop();
}
setf a 5
(setf a 5)
((setf a 5))
void a_fun(void)
{{
}}
void a_fun(void)
{{{
}}}
void a_fun((void))
{
}
fun_d( fun_c( fun_b( fun_a())));
fun_d( fun_c( fun_b( fun_a()
                   )
             )
      );
(setf a 5)
setf(a 5)
eval(setf a 5)