Scheme和Common Lisp之间的实际区别是什么?(或Lisp的其他两种方言)


78

注意:我不是在问要学习哪个,哪个更好或者类似的东西。

我选择了SICP的免费版本,因为我觉得读起来会很高兴(我听说过很多不错的东西,并且我对编程的这种方面很感兴趣)。

我知道Scheme是Lisp的方言,我想知道:Scheme与Common Lisp之间的实际区别是什么?

似乎有很多关于“ CL具有更大的stdlib ...方案对于实际编程不利的..”,但实际上并没有说“这是因为CL是这个/拥有这个”。


4
“该方案不利于现实世界的编程”……我在Scheme中进行现实世界的编程(好的,不多)。
knivil 2011年

不知道这是否是潜台词,但我建议仅在Scheme中进行SICP练习。您几乎可以使用带有正确参数的任何实现,因为它们关注的子集很小。您只需要找到适合您选择的参数,例如,在Racket中,它可能是R5RS模式。即使您继续使用Common Lisp甚至Clojure,SICP的许多想法也将帮助您进一步进行Lisp研究。
michiakig 2011年

11
上次我看到,Scheme规范大约有50页,而CL规范则超过1000。因此,只要将CL规范打开到任何页面,机会就很大,这在CL中却不是Scheme。:-)

@knivil我是从其他SO问题中引用的,这些问题已经见过。
共产党鸭子

Answers:


99

这是一个棘手的问题,因为差异既是技术上的,(更重要的是,我认为)是文化上的。答案只能提供不精确,主观的观点。这就是我要在这里提供的。有关一些原始技术细节,请参阅Scheme Wiki

Scheme是一种语言,它基于提供优雅,一致,经过深思熟虑的基本语言基础的原则,可以在此基础上构建实践和学术应用语言。

您很少会发现有人用纯R5RS(或R6RS)Scheme编写应用程序,并且由于极简的标准,大多数代码无法在Scheme实现中移植。这意味着,如果您要编写某种最终用户应用程序,则必须仔细选择Scheme实施,因为这种选择将在很大程度上决定您可以使用哪些库。另一方面,设计实际应用程序语言的相对自由度意味着Scheme的实现通常提供其他地方闻所未闻的功能。例如,PLT Racket使您能够使用静态类型并提供非常了解语言的IDE。

通过社区驱动的SRFI流程提供了超越基本语言的互操作性,但是任何给定SRFI的可用性都因实施而异。

大多数Scheme方言和库都专注于函数式编程习惯用法,例如递归而不是迭代。要进行OOP时,可以将各种对象系统作为库加载,但是与现有代码的集成在很大程度上取决于Scheme方言及其周围的文化(例如,Chicken Scheme比Racket更面向对象)。

交互式编程是Scheme子社区与众不同的另一点。MIT Scheme以强大的交互性支持而闻名,而PLT Racket则感觉更加静态。无论如何,交互式编程似乎并不是大多数Scheme子社区的中心问题,而且我还没有看到像大多数Common Lisps一样具有交互性的编程环境。

Common Lisp是为实际编程而设计的一种经久不衰的语言。它充满了丑陋的疣和兼容性漏洞-与Scheme优雅的极简主义相反。但是,当它自己使用时,它的功能也更加丰富。

Common Lisp孕育了一个相对大型的可移植库生态系统。通常,即使在应用程序部署之后,您通常也可以随时切换实现,而不会遇到太多麻烦。总体而言,Common Lisp比Scheme更统一,并且如果要进行更彻底的语言实验,则通常将其嵌入为可移植库,而不是定义一个全新的语言方言。因此,语言扩展往往更保守,但也更易于组合(通常是可选的)。

诸如外部功能接口之类的通用语言扩展不是通过正式方式开发的,而是依赖于所有主要Common Lisp实现上可用的准标准库。

语言习语是功能,命令式和面向对象方法的狂野混合,一般而言,Common Lisp感觉更像是命令式语言,而不是功能性语言。它也具有极强的动态性,可以说比任何一种流行的动态脚本语言都更具动态性(例如,类重新定义适用于现有实例,并且条件处理系统内置了交互性),而交互式探索性编程是其中的重要组成部分“常见的Lisp方式。” 这也反映在Common Lisp可用的编程环境中,几乎所有环境都提供了与正在运行的Lisp编译器的某种直接交互。

Common Lisp具有内置对象系统(CLOS),条件处理系统的功能,它比单纯的异常处理,运行时可修补性以及各种内置数据结构和实用程序(包括臭名昭著的LOOP宏,迭代)要强大得多。子语言对Scheme来说太丑陋了,但更不用说了,以及在格式字符串中具有GOTO支持的类似printf的格式化机制。

既由于基于图像的交互式开发,又由于语言较大,Lisp实现通常在整个操作系统中的可移植性低于Scheme实现。例如,让Common Lisp在嵌入式设备上运行并不意味着胆怯。与Java虚拟机类似,在受虚拟内存限制的计算机(例如基于OpenVZ的虚拟服务器)上,您也往往会遇到问题。另一方面,方案的实现往往更紧凑和可移植。尽管ECL实施的本质仍然是正确的,但其质量不断提高已在一定程度上缓解了这一点。

如果您需要商业支持,则有几家公司提供自己的Common Lisp实现,包括图形GUI构建器,专用数据库系统等。

总结一下,Scheme是一种设计更为优雅的语言。它主要是一种具有某些动态功能的功能语言。它的实现代表具有独特功能的各种不兼容方言。Common Lisp是一种成熟的,高度动态的,多范式的语言,具有各种丑陋但实用的功能,其实现方式在很大程度上相互兼容。与Common Lisp相比,方案的方言往往更静态,交互性更低。常见的Lisp实现往往更重且安装更麻烦。

无论选择哪种语言,祝您玩得开心!:)


7
should you want to write some kind of end-user application+1
kmoe

21

基本的实际差异:

  • Common Lisp对变量和函数有单独的作用域;而在Scheme中,只有一个范围-函数是值,定义具有特定名称的函数只是定义为lambda设置的变量。结果,在Scheme中,您可以将函数名称用作变量,并将其存储或传递给其他函数,然后对该变量进行调用,就好像它是一个函数一样。但是在Common Lisp中,您需要使用显式地将函数转换为值(function ...),并使用显式调用存储在值中的函数(funcall ...)
  • 在Common Lisp中,nil(空白列表)被认为是错误的(例如if),并且是唯一的false值。在Scheme中,空列表被认为是true,并且(distinct)#f是唯一的false值

对我来说,到目前为止,@ newacct提出的第一点是最重要的。如果函数不是一流的对象,那么我会失去很多真正有趣的“创造性”编程感觉。好的,关于速度等可能有“实用”的考虑,但是,如果我要使用功能不变的编程,恕我直言。如果我需要实用性,我可以去Clojure并获得两全其美。Common Lisp有它的位置,但是我怀疑它在“工业”领域中,我相信人们对此非常感激。
亚历克斯·吉安

2
CL仍然具有一流的功能。它拥有功能不同的命名空间,并不意味着它不具备一流的功能(是的,有一个需要多一点语法,但仅此而已)。
mwal19年

回复:在CL中起作用,更大的障碍是缺乏强制性TCO。当然,有些实现支持它,但是那意味着您不再编写可移植的CL代码了,可移植性似乎是主要吸引点之一
Coderino Javarino

8

很难公正地回答这个问题,特别是因为许多LISP人士会将Scheme归类为LISP。

乔什·布洛赫(Josh Bloch)(这种类推可能不是他的发明)将选择语言描述为类似于选择本地酒吧。鉴于此,那么:

“ Scheme”酒吧中有许多编程语言研究人员。这些人在语言的含义,保持其定义和简单性以及讨论创新的新功能上花费了大量精力。每个人都有自己的语言版本,旨在使他们能够探索自己的编程语言的特定角落。Scheme的人们真的很喜欢他们从LISP中获取的括号语法;它灵活,轻便,统一,消除语言扩展的许多障碍。

“ LISP”酒吧?好吧...我不应该发表评论;我在那里的时间还不够:)。


2

方案:

  • 本来规格很少(新的R7RS似乎更重)
  • 由于语法简单,因此可以快速学习方案
  • 实现提供其他功能,但在不同实现中名称可能有所不同

普通口齿不清:

  • 更大的规格定义了许多功能
  • 函数和变量的不同名称空间(lisp-2)

有一些要点,当然还有更多,我现在不记得了。


1
您参考“ RSR7”;而是应为“ R6RS”。
约翰·克莱门茨
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.