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