如何有效地读写Lisp代码?

如何有效地读写Lisp代码?,lisp,common-lisp,readability,code-readability,Lisp,Common Lisp,Readability,Code Readability,我目前正在学习Lisp,我认为我已经掌握了基本知识(我正在使用优秀的Lisp书籍,到目前为止,我已经阅读并完成了大约四分之一的学习) 我尝试根据我所学的知识创建自己的Lisp程序。不知怎的,它起作用了。但这只是不知怎么的。到目前为止,我主要使用C语法的语言进行开发,如C#和JavaScript(请注意,我非常清楚JavaScript不是基于C的语言) 尽管如此,我习惯于用C语法“思考”,当我用C#或JavaScript编写代码时,我可以用一种非常简单的方式写下来。相反,在编写Lisp代码时,我很

我目前正在学习Lisp,我认为我已经掌握了基本知识(我正在使用优秀的Lisp书籍,到目前为止,我已经阅读并完成了大约四分之一的学习)

我尝试根据我所学的知识创建自己的Lisp程序。不知怎的,它起作用了。但这只是不知怎么的。到目前为止,我主要使用C语法的语言进行开发,如C#和JavaScript(请注意,我非常清楚JavaScript不是基于C的语言)

尽管如此,我习惯于用C语法“思考”,当我用C#或JavaScript编写代码时,我可以用一种非常简单的方式写下来。相反,在编写Lisp代码时,我很难将注意力集中在这些括号上

如果我有一个简单的陈述,比如

(setf x (+ 2 3))
我总是试图从左到右阅读它,发现它不起作用,然后搜索最里面的一对括号,然后把它翻过来。对于这个简单的表达式,它的工作速度相当快

但是如果我有更复杂的代码(尽管它还不复杂),比如说使用
let
的函数,那么(至少对我来说)很难找到最里面的一对括号:

(defun foo ()
  (let ((x 23)
        (y 42))
  (+ x y)))
在这里,已经有点难以看到什么之后发生了什么,以及什么嵌套到了什么。现在添加一些
cond
东西,也许再加上一些
lambda
s,我完全迷路了,发现自己数了几分钟括号(字面意思)

写它的时候也是如此,我被括号的数量弄得不知所措,我甚至认为我还没有看到“复杂”的Lisp代码


随着时间的推移,情况会好转吗?也就是说,你习惯了吗?或者,在如何阅读和编写Lisp代码以使事情变得更简单方面,有什么诀窍吗?更有经验的Lisp程序员是如何做到这一点的?有什么提示吗?

您需要正确缩进它。你的例子不是

(defun foo ()
  (let ((x 23)
        (y 42))
  (+ x y)))
在这里:

最后一个表达式需要向右移动。然后你可以看到它在LET里面

Lisp有一些结构模式。不太多。一旦您学习和训练了这些,阅读Lisp就相对容易了。学习汉语比学习汉语要容易得多,因为汉语被更多的人阅读

一些模式:

(symbol ...)
符号表示锚

((a 10) (b 20))
绑定列表,例如在
LET

(with-foo (foo :option1 1 :option2 2)
  (body))
宏,如
和-OPEN-FILE

然后是复杂函数arglist本身。位置参数、可选参数、关键字参数<代码>&rest和
&aux

还有一些,但不是太多。一旦您了解了基本的宏和特殊的表单模式,代码读取就会变得容易得多

如何改进?读代码。火车。其实并不难。有点像骑自行车。最初的日子似乎很艰难,然后就自动化了

写作。

要编写代码,您需要一个可以缩进的编辑器。大多数只能缩进行,但不能格式化整个表达式。因此,您需要进行格式化。这里有一些基本规则。Lisp有一个漂亮的打印机,可以格式化。但这在编辑器中通常是不可用的,而且它不知道诸如注释之类的事情

当我编写一段Lisp代码时,我通常也会花一些时间来正确布局代码

  • 台词太长
  • 悬空括号
  • 结构正确吗
  • 路线
  • 有足够的视觉线索吗
  • 命名
  • 评论
  • 文件

我也是Lisp新手。然而,我发现它相对容易学

在我看来,要记住的主要一点是Lisp是抽象语法树的直接表示。当其他语言是面向文本的,并且它们的语法被建模为更接近人类语言时,Lisp是面向树的。因此,它需要一种完全不同的阅读和写作方式。如果你在数括号,你就做错了

您应该学习将lisp代码作为树来阅读。使用正确的压头,它将自动表示为这样,s表达式的第一个标记表示任何子树的根。因此,布局类似于树状视图中的布局,例如Windows资源管理器中的左侧

也许这对我来说更容易,因为我已经编写了直接在C/C++代码的AST上工作的分析软件。我记得当时从了解源代码到理解AST并不容易,我一直犯错误,如果我考虑AST,而不是总是考虑源代码,我本可以避免这些错误


因此,我建议使用emacs编写代码。ParEdit阻止您将Lisp代码编写为文本,而是允许(或强制,不管您如何称呼它)您直接编写和转换AST。

使用自动缩进代码的编辑器,如Emacs,使结构可见。例如,在上一个示例中,
(+xy)
应该再缩进两个空格,这样您就可以看到它是
let
.Hm的主体。这有助于写作,但阅读又如何呢?例如,当我阅读StackOverflow上的代码时;-)?代码正确缩进后,几乎可以忽略括号。随着时间的推移,你会习惯像
defun
let
这样的常用习惯用法。只是为了升华而安装的,事实上,自动缩进真的很有帮助。惊人:-)。谢谢你的提示!你是对的。JavaScript、C++、java、perl、C++和C++都是大方言。它很容易阅读,因为你知道Algol的语法。常见的lisp和Scheme都是lisp方言,如果你知道其中一种,就很容易读懂。非常有用的答案(就像我读过的所有答案一样)!感谢您在SO:-)上做了这么大的工作,现在十天过去了,我已经阅读和编写了一些Lisp代码,我不得不说,所有这些括号的危害比我一开始预期的要小得多
(with-foo (foo :option1 1 :option2 2)
  (body))