Featured image of post Lisp有什么不同

Lisp有什么不同

深入解析Lisp语言的九个创新特性,及其对现代编程语言的影响。

📚 返回 Paul Graham 文章目录

Lisp有什么不同

2001年12月(2002年5月修订)

(本文是对LL1邮件列表上一些问题的回应。现在已收录在Revenge of the Nerds中。)

当McCarthy在1950年代末设计Lisp时,它与现有语言有着根本性的不同,其中最重要的是Fortran

Lisp包含了九个新思想:

  1. 条件语句。条件语句是一种if-then-else结构。现在我们认为这是理所当然的。它们是由McCarthy在开发Lisp的过程中发明的。(当时的Fortran只有基于底层硬件分支指令的条件goto。)McCarthy作为Algol委员会的成员,将条件语句引入了Algol,之后它们传播到了大多数其他语言。

  2. 函数类型。在Lisp中,函数是一等对象——它们是一种数据类型,就像整数、字符串等一样,有字面表示,可以存储在变量中,可以作为参数传递,等等。

  3. 递归。递归在Lisp之前就作为数学概念存在,但Lisp是第一个支持它的编程语言。(这可以说是将函数作为一等对象的必然结果。)

  4. 变量的新概念。在Lisp中,所有变量实际上都是指针。值才有类型,而不是变量,赋值或绑定变量意味着复制指针,而不是复制它们指向的内容。

  5. 垃圾回收

  6. 由表达式组成的程序。Lisp程序是表达式树,每个表达式都返回一个值。(在某些Lisp中,表达式可以返回多个值。)这与Fortran和大多数后续语言形成对比,后者区分表达式和语句。

在Fortran中这种区分是很自然的,因为(在一个输入格式是穿孔卡片的语言中并不奇怪)该语言是面向行的。你不能嵌套语句。因此,虽然你需要表达式来进行数学运算,但让其他任何东西返回值都没有意义,因为不会有任何东西在等待它。

这个限制随着块结构语言的到来而消失,但那时已经太晚了。表达式和语句之间的区分已经根深蒂固。它从Fortran传播到Algol,然后传播到它们的后代。

当一个语言完全由表达式组成时,你可以随心所欲地组合表达式。你可以说(使用Arc语法):

(if foo (= x 1) (= x 2))

或者

(= x (if foo 1 2))

  1. 符号类型。符号与字符串的区别在于你可以通过比较指针来测试相等性。

  2. 使用符号树的代码表示法

  3. 整个语言始终可用。在读取时、编译时和运行时之间没有真正的区别。你可以在读取时编译或运行代码,在编译时读取或运行代码,在运行时读取或编译代码。

在读取时运行代码让用户可以重新编程Lisp的语法;在编译时运行代码是宏的基础;在运行时编译是Lisp在Emacs等程序中作为扩展语言使用的基础;在运行时读取使程序能够使用s表达式进行通信,这个想法最近被重新发明为XML。

当Lisp首次发明时,所有这些思想都与1950年代末硬件所决定的普通编程实践相去甚远。

随着时间的推移,体现在一系列流行语言中的默认语言逐渐向Lisp演变。1-5现在已经广泛传播。6开始出现在主流中。Python有7的一种形式,尽管似乎没有它的语法。8(与9一起)是使Lisp宏成为可能的原因,到目前为止仍然是Lisp独有的,可能是因为(a)它需要那些括号,或类似的东西,以及(b)如果你添加那个最终的力量增量,你就不能再声称发明了一种新语言,而只是设计了一种新的Lisp方言;-)

尽管对当今的程序员有用,但用Lisp与其他语言采用的随机权宜之计的差异来描述它很奇怪。这可能不是McCarthy的想法。Lisp并不是为了修复Fortran的错误而设计的;它更像是公理化计算尝试的副产品。

这也不是始于Lisp并传播到其他语言的想法的完整列表。这些只是初始集合。在后续的Lisp实现中开发了更多,包括延续、多返回值、剩余参数和赋值(setf)反转。

英文版:paulgraham.com/diff.html|中文版:HiJiangChuan.com/paulgraham/012-what-made-lisp-different

📚 返回 Paul Graham 文章目录

更新记录: