我目前正在学习Lisp,我认为我掌握了基础知识(我使用了优秀的书 Land of 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
,我完全迷失了,发现自己数了几分钟(字面意思)括号。
写作时也是如此,我对括号的数量感到迷茫,我不认为我甚至看到过#34;复杂的" Lisp代码。
随着时间的推移会变得更好吗?即,你习惯了吗?或者,有没有关于如何处理读取和编写Lisp代码以使事情变得更容易的技巧?经验丰富的Lisp程序员如何做到这一点?任何提示?
答案 0 :(得分:10)
您需要正确缩进。你的例子不是。
(defun foo ()
(let ((x 23)
(y 42))
(+ x y)))
下面:
(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))
像WITH-OPEN-FILE
这样的宏。
然后是复杂的函数arglist本身。位置参数,可选参数,关键字参数。 &rest
和&aux
。
还有一些,但不是太多。一旦学会了基本的宏和特殊表单模式,代码阅读就变得容易了。
如何改进?阅读代码。培养。这并不难。有点像骑自行车。第一天似乎很难,然后它是自动化的。
<强>书写。强>
要编写代码,您需要一个可以缩进的编辑器。大多数只能缩进行,但不能格式化整个表达式。因此,您需要进行格式化。有一些基本规则。 Lisp有一台漂亮的打印机,可以格式化。但这通常在编辑器中无法使用,而且它不知道评论等内容。
当我编写一段Lisp代码时,我通常会花一些时间来正确编写代码。
答案 1 :(得分:4)
我也是Lisp的新手。但是,我觉得它相对容易学习。
IMO要记住的主要事情是Lisp是抽象语法树的直接表示。如果其他语言是面向文本的,并且它们的语法被建模为更接近人类语言,那么Lisp是面向树的。因此,它需要一种完全不同的阅读和写作方式。如果您正在计算括号,那么您做错了。
您应该学会将lisp代码作为树来阅读。使用正确的压头,它将自动表示为这样,s表达式的第一个标记表示任何子树的根。因此,布局类似于树视图中的布局,例如, Windows资源管理器中的左侧。
也许这对我来说更容易,因为我编写了直接使用C / C ++代码的AST的分析软件。我记得那时从了解源代码到理解AST的步骤并不容易,我一直犯错误,如果我考虑过AST,我可以避免这种错误,而不是总是考虑源代码。
出于这个原因,我推荐ParEdit用于编写代码的emacs。 ParEdit阻止你编写Lisp代码作为文本,而是允许(或强制,但你想调用它)你直接编写和转换AST。