理解 LISP 的语法

Understanding the syntax of LISP

虽然 LISP 有一些我见过的最简单的语法,但我仍然对基本原理感到困惑。我做了研究,得出的结论是有两种数据类型:"atoms" 和列表。但是,我也遇到了术语 "S-expression",它似乎同时描述了原子和列表。那么,S表达式到底是什么?它是一种数据类型吗?此外,我不确定如何在 LISP 中区分函数调用和数据列表。例如,(1 2 3) 是一个列表,而 (f 2 3) 可能是某个函数。但是我怎么知道 f 是一个函数名还是某种数据类型呢?由于列表和函数使用相同的语法,我不确定如何区分两者。最后,最重要的是,我需要一个思维模型来思考 LISP 的工作原理。例如,什么是基本数据类型?用于处理基本数据类型的内置过程是什么?我们如何才能将数据和程序视为截然不同的呢?例如,在Java中,类顶部的实例变量用于表示数据,而方法是操作数据的过程。这在 LISP 中看起来像什么?

(我是新手,不知道这个问题是不是太宽泛了)

一切自我评价的都是数据。例如 2"hello"。 引用的所有内容都是数据。例如 '(f 3 4)'test 或普通版 (quote test) 提供给 REPL 的所有其他内容都需要是代码。例如 (f 3 4) 是代码。它是 s 表达式,与上面引用的数据无法区分,但它没有被引用,所以它必须是代码。

有一些特殊形式,例如 ifletlambdadefun,...您只需要了解其工作原理即可。你怎么知道 if 不是像 Java 或 C# 这样的 C 方言中的方法?你只需要记住它们。

您还需要了解一些基本功能。通常它们与特殊形式一起在每个教程中介绍。我建议您阅读 Land of Lisp and Practical Common Lisp for Common Lisp and Realm of Racket and How to design programs for Racket. For pure Scheme I recommend The wizard book (SICP)。不要同时做所有这些。当你学会一个很好的时候,学习其他的就很容易了。

现在学一门Lisp比学一门C方言还难。这是因为它是一种完全不同的语言,具有不同的做事方式。例如。你不会发现 forwhile 循环和变量没有类型但它们引用的对象有。您需要学习如何编程,就好像您不懂 C 方言一样。 (实际上,会C方言可能会使学习变得更难)

祝你好运!

一个 "S-expression" 是 'an atom, or a list of S-expressions'(这里有一些更复杂的问题,我现在将跳过这些,基本上归结为一个叫做 "read macros" 的东西,其中可以做文本表示和内部表示,简化人的书写)。

(1 2 3) 是一个列表。但是,(f 1 2 3) 也是一个列表。但是,在某些(大多数?)情况下,它也可以是函数调用(而不是函数)。

我认为您主要了解了语法,其余的是语义(在非常技术的意义上)。在这一点上,我会指出一些好的阅读 material,周围有很多好书(我从 Winston-Horn's "Lisp" 的早期版本开始。

我支持 LispBook 和 Practical Common Lisp 的推荐。两本好书。一旦您了解了基础知识,我真的非常推荐 Paul Graham's "On Lisp"

指导您找到特定问题的答案:

  1. 数据类型:Lisp 有一组丰富的数据类型(数字类型,如整数、有理数、浮点数——字符和字符串——数组和哈希表——还有很多),但在我看来,假设您已经熟悉整数和字符串,您应该首先阅读 symbolcons.

  2. symbol:认识到一个符号既是一个标识符又是一个值。了解每个符号可以 "point to" 一个数据值,同时 "point to" 一个函数(并且具有您还不需要担心的其他三个属性)

  3. cons:发现这个叫做 'cons cell' 的神奇东西只是一个有两个指针的结构。一个叫 "the Address part of the Register",另一个叫 "the Decrement part of the register"。不用担心这些名称的含义(它们不再相关),只要知道 car 函数 returns 寄存器地址部分的内容,以及 cdr returns 减量部分。现在忘掉所有这些,记住现代 Lispers 认为 cons 单元格是一个有两个指针的结构,一个叫做 car,另一个叫做 cdr。

  4. 列表:"There is no spoon."也没有列表。意识到我们认为的列表无非是一组cons cells,每个cons的car指向列表中的一个成员,每个cons的cdr指向下一个cons(除了最后一个cons ,其 cdr 为 "the null pointer" nil)。这对于理解列表操作、嵌套列表、树结构等至关重要。

  5. 原子:现在,将原子想象成数字、字符、字符串或符号。这足以让您入门,您可以稍后深入了解细节。

  6. S-表达式:一个 s-expr 被定义为 "either an atom, or a cons cell pointing to two s-expressions"。现在不要担心什么是或不是 s-expr,但是 checkout wikipedia for a brief intro

  7. 列表与函数调用:伙计,噢,伙计!当我开始时,我为此苦苦挣扎!但实际上只要稍加练习就很容易:"Five times two" 只是一个英文短语,对吧?但是如果我让你 "evaluate" 它,你可能会说 "ten"。 “1 + 2”是一个数学表达式,但数学家会将其计算为 3。“5”只是一个数字,但如果您将其输入计算器并按“=”,计算器会将其计算为答案 5 . 在 Lisp 中 (+ 1 2) 只是一个列表。它是一个包含符号 +、数字 1 和数字 2 的列表。但是 - 如果您要求 Lisp 计算该列表,它将调用函数 +,将 1 和 2 作为参数传递给它.熟悉 Lisp 的很大一部分是了解何时何地对 s-表达式求值,以及在哪里不求值。现在 - 您在 REPL 中键入的任何内容都将被评估,函数调用的参数将被评估,宏调用的参数可能不会被评估,您可以使用 quote 来防止评估。通过练习,会变得更容易。

  8. 基本功能:虽然我说了"list"并不存在("Its conses all the way down, Mr. Fry"),但还是先学习列表的东西,carcdrconslistappendreverse 和应用程序 mapcarmapconsapply。这些是开始思考列表和函数式编程的好方法。

  9. 类,成员数据和方法:我建议把面向对象留到以后再说。首先学习Lisp的基础知识。在您熟悉语言本身之前,不要担心数据封装、访问控制和多态性。准备就绪后,请阅读 "On Lisp",第 25 章将引导您自己将面向对象添加到 Lisp 中,展示 Lisp 如何真正成为一种可编程的编程语言。然后本书将向您介绍 CLOS,Common Lisp 中内置的标准面向对象系统。了解 CLOS,但一定要浏览其他 OO 库。 Lisp 是我知道的唯一一种语言,您可以在其中实际选择 如何 您希望该语言实现 OO。

我要到此为止了。熟悉上面的前 8 个概念,一个强大的心智模型就会自行解决。