"Lisp可以自己编写吗?"是什么意思?

Mas*_*ler 21 lisp programming-languages

Paul Graham写道:"关于Lisp的不寻常之处 - 事实上,Lisp的定义质量 - 就是它可以自己编写." 但这对我来说似乎没有什么不寻常或明确的.

ISTM,编程语言由两个东西定义:它的编译器或解释器,它通过fiat定义语言的语法和语义,以及它的标准库,它在很大程度上定义了熟练用户将使用的习语和技术.用语言编写代码.

除了一些特定的例外(例如,.NET系列的非C#成员),大多数语言的标准库都是用这种语言编写的,原因有两个:因为它将共享同一组语法定义,函数调用约定,以及语言的一般"外观和感觉",并且因为可能为编程语言编写标准库的人是其用户,特别是其设计者.所以那里没什么特别的; 这是非常标准的.

再一次,语言编译器本身就没有什么独特或不寻常的东西.C编译器用C语言编写.Pascal编译器用Pascal编写.Mono的C#编译器是用C#编写的.哎呀,即使是一些脚本语言也有"自己编写"的实现.

那么Lisp在编写本身时是不寻常的意味着什么呢?

Nor*_*sey 11

保罗的意思可能是Lisp 语法作为Lisp 值的表示是标准化和普遍的.也就是说,Lisp程序只是一种特殊的S表达式,编写操作Lisp代码的Lisp代码非常容易.在Lisp中编写Lisp解释器是一种特殊情况,并不像对代码和数据进行统一表示的一般能力那样令人兴奋.

  • 您所描述的是[homoiconic](http://en.wikipedia.org/wiki/Homoiconic)语言的属性,这也是其他语言共享的特征. (7认同)

650*_*502 7

我刚刚删除了很长的回复,这可能不合适.

但请考虑:

  1. LISP没有"语法",如果你的意思是它具有C/Java/Pascal等语言的含义...... Common LISP阅读器有一个(初始但可自定义的)语法,但这是另一回事(LISP,Graham正在谈论的不是普通的LISP,而且(读者)不是LISP语言,而只是一个程序).像"(lambda(x)(*x 2))"这样的东西不是 LISP代码,而是例如CL标准阅读器可以转换为LISP代码的文本.

  2. LISP不仅可以用LISP编写(如果你的意思是"bootstrap"能力),它实际上就是以这种方式存在的.20世纪50年代后期eval的第一次实现是用LISP写在纸上,然后手动转换成机器语言(1):LISP起初是一个纯粹的理论思想,并不是要实现的.我知道没有其他计算机语言遵循这条道路.例如,C++被认为是C编译器的预处理器,并且是用C语言编写的,它不是一个C++程序,后来转换为C才能运行它.

LISP还有许多其他方面的不同之处,我认为掌握它的最佳方法是实际实现玩具LISP解释器(如果你的"机器语言"是像Python这样的高级动态类型语言.

(1)在http://www-formal.stanford.edu/jmc/history/lisp/node3.html中你可以找到McCarthy如何描述eval[e, a]在纸上首先发现的一个有趣的理论结果(一个"通用功能"实现整理器而不是一个通用的图灵机)只有数据结构和基本的本机功能已经为该组正在构建的Lisp语言布局.这个手写功能由SR Russell在机器代码中手动实现,并开始作为第一个Lisp解释器提供服务.


Rob*_*vey 6

那么,你提供的链接会继续说,如果你继续阅读,他会详细回答你的问题.

关于Lisp的不寻常的事情 - 实际上,Lisp的定义质量 - 就是它可以自己编写.为了理解麦卡锡的意思,我们将回溯他的步骤,将他的数学符号转换为运行Common Lisp代码.

  • 是的,然后文章结束了. (2认同)

Chu*_*uck 6

他并不是说Lisp可以用来编写Lisp编译器.他说这种语言是由自己的数据结构组成的.因此,虽然您无法使用C数据结构构建C函数,但您可以在Lisp中执行此操作.程序由您的计算机执行的列表组成,这些列表的效果可以是创建随后执行的其他列表,这些列表的效果可以是创建更多要执行的列表.C没有这个属性.例如,C代码不能操纵自己的AST.

  • @wallacoloo:这里的*language*和*implementation*之间有一个微妙的区别.C代码不能操作**本身**,但它可以操纵它实现的**机器语言**代码.这是一个完全不同的抽象级别,在Lisp中操作Lisp代码. (5认同)

Rai*_*wig 5

主要思想是语言 Lisp 有一个非常小的内核,只有少数函数,主要的评估机制可以写在一个页面上的代码中。

这就是Lisp核心

要了解该语言的基本工作原理,只需查看该单页代码:它解释了变量如何工作、函数调用如何工作、如何创建新函数等。

想想你可以从语言实现中删除多少以获得基础知识。什么是最小原语集,什么是最小执行引擎。要在 Lisp 中编写 Lisp,您几乎什么都没有。

如果您查看 PASCAL 实现(作为示例),它不是在 PASCAL 中实现的,而是在 PASCAL 中实现的 + 大量代码,这些代码提供了表示语言实体、解析器、编译器、运行时、. .. - 开箱即用的 PASCAL 没有提供太多 - 必须构建这些(或使用库)。

Wirth(Pascal 的创建者)写了一本书,解释了一种非常小的类似 Pascal 的语言的实现——你仍然需要编写大量代码来实现这种语言——解析器、代码生成器、运行时、加载器……

相比之下,在 Lisp 中,Lisp 源代码具有自然的表示形式,评估 Lisp 代码的核心例程只是一个 Lisp 函数。这可能不是真正或实用的 Lisp 实现,但它仍然不同于 PASCAL 情况,在 PASCAL 情况下,源代码没有有用的表示(除了字符串或文件)并且执行引擎是更多的代码。

所以在 Lisp 中,我们有:

  • 源代码的简单表示(符号列表)

  • 评估器在单个小函数中的简单实现

除此之外,在 Lisp 中实现 Lisp 求值器不需要什么。