在两个Lips之间

2020-12-06 00:16:54

在所有Lisps中,我最欣赏的是Scheme和Common Lisp。这两种语言在本质上是完全不同的:Scheme是在lambdacalculus的基础上构建的极简主义语言,而Common Lisp是许多Lisps优先级的多范式综合。 Common Lisp是具有许多实现的大型标准,Scheme是许多实现的但极简的标准的集合。与Common Lisp相比,Scheme的核心很小。最新的标准R6RS约为65页,而1994年的ANSI Common Lisp标准约为1100页。计划实施方案过程旨在标准化实施可能实现的其他功能(例如测试套件)。

Common Lisp具有一些出色的功能,条件和重新启动功能,CommonLisp对象系统(CLOS),宏系统等等。用于Emacs的SLYIDE很棒,而Steel Bank Common Lisp编译器确实很棒。它分别具有Quicklisp和ASDF,用于打包和生成管理。我发现Common Lisp的开发人员经验几乎胜过任何可以想象的事情,这不是一个空洞的声明:使用各种IDE和编辑器已有25年以上,我已经看到了很多。

就是说,Common Lisp很奇怪。我特别感到震惊的是,函数和变量存在于不同的命名空间中:如果将函数放入变量中,不仅不能像函数一样使用它,还必须对其进行有趣的调用。使用ML系列的许多语言进行编程只是,很好,很奇怪;但这是由于历史原因,并且有合理的技术原因。还有其他的问题,例如(cdr'())并非错误(在Scheme itis中),()和nil相等(在Scheme #f和()中是独立的事物)等等。

这并不是Common Lisp的错:其他语言已经影响了我的品味和偏好,使我偏向Scheme的方向,但这并不是说我无法使用Common Lisp的特质。其实,我不在乎它们,我只是注意到它们。

我也更喜欢Scheme的命名风格。它有绳子吗? vs string-pfor谓词函数,设置!对于状态修改功能,通过foo-> bar进行转换,这些使代码更易于阅读。 Scheme具有卫生宏,Guile也具有传统的defmacro。

Common Lisp库中提供了许多不错的Scheme功能。模式匹配在trivia库中可用。命名let易于使用宏实现。

常见的Lisp爱好者会很快指出Scheme所没有的东西:关键字参数,文档字符串,其余参数,但我在选择Guile的Scheme实施中已将其内置于该语言中。

Guile处于一个奇怪的位置,它的主要存在理由是成为GNU项目的扩展语言。就像Emacs Lisp用于扩展Emacs一样,Guile是GNU程序用于扩展和脚本编写的事实上的语言。

Guile没有Quicklisp及其程序包管理器,而第一个基本上不存在构建系统,第二个基本上没有Autoconf。在Guile社区中有一种使Guix成为Guile的软件包管理器的想法。这可能听起来有点麻烦,因为Guix也是Guile之外其他功能的完整软件包管理器,但请考虑一下:正如Andy Wingopoint在其信息中指出,Guile库通常带有C扩展,Guile软件包需要某种托管构建系统用于构建扩展。由于它没有一个,要解决构建程序包管理器的问题,您还必须构建一个可以管理C代码和C代码位所需的程序包的构建系统。优雅地做到这一点是一项艰巨的任务,例如,chicken-install仅要求您在调用命令行之前将编译器/链接器标志放在命令行中,因此显然这是一个难题。

现在,Guix以非常优雅和有趣的方式解决了所有这些问题。但是它不像Quicklisp或CHICKEN Scheme的鸡肉安装那样轻巧。而且,Guix实际上只能在GNU / Linux系统上运行,因此,如果您打算通过Guix分发它,那么macOS和Windows用户将无法使用您的库。嗯,这是GNU项目,但是可移植性总是很好。

但是在Common Lisp中,我可以编写(ql:quickload:alexandria)和voilà,它将自动安装我可以使用的Alexandria库。再说一次,在InCommon Lisp中,具有C扩展名的情况比较少见,所以我不知道ASDF是如何处理的。

将SLY与最好的Emacs Scheme集成包Geiser进行比较是不公平的。 SLY基于SLIME,SLIME拥有数十年的工作量。 Geiser能够支持多个Scheme实施,并且在这方面令人印象深刻。但是SLY显然拥有更多功能(例如,交互式调试器)。就是说,Geiser对Guile有很好的支持,并且Guile通常是所有Scheme中最常见的Lisp-y,实际上,它具有

还有一些不错的事情,例如Common Lisp的一流延续性。但是话又说回来,我很少使用那些。

如果要编写一个我知道需要使用低级语言的可扩展C / C ++ / Rust程序,则可以使用低级语言来做低级位,然后用Guile编写其余部分。通过Guile,可以很容易地将REPLsocket转换为可以连接的myprogram --repl = 12345之类的东西,并且C和Guile之间的互操作非常棒,因为它主要是扩展语言。

另一方面,如果要构建一个完全独立的应用程序,那么选择就不那么明显了。我可以用任何一种语言完成全部操作。 Common Lisp可以构建本机可执行文件,尽管它们的大小很大(谁在乎?),因为二进制文件将包含整个Lisp实现。 Guile无法编译协调性代码,因此您必须编写脚本可执行文件,但这并不是必须的。

当我制作一个必须具有一些C / C ++位但要使它可由用户编写脚本的可扩展程序时

当我想编写本机二进制文件而不写太多C / C ++代码时

另一方面,如果我只想享受快速的快速开发经验,大型标准库和语言,并且我不介意拥有50MB的二进制文件(同样,谁在乎?),Common Lisp最有意义。程式。 Guile无法做到这一点,但是编写Guilescripts或本质上引导二进制文件以加载Schemeruntime的C程序很容易。例如,这就是LilyPond的编写方式。

因此,答案无疑是两者!两种语言的编写都非常有趣。目前,我不在日常工作中执行Lisp,所以这一切都是为了娱乐。如果这是出于专业目的,我不知道。通常,对专业工作的严格要求是要有生产力。在这种情况下,我认为Common Lisp具有显着的优势,这不仅是由于其卓越的开发经验,而且还因为其作为一种实际的生产语言的历史。有一些实际公司在Common Lisp中做事。我没有听说过Guile的任何专业用途(工业意义上的用途),尽管Guile支持的许多项目(Guix等)在编写和维护方面都非常专业。但是Common Lisp背后有更多的图书馆和公司。

实际上,我很乐意将Clojure用于个人娱乐,并且需要一些专业知识。我写了两个库(警戒和任务),我的经验一直很积极,其开发经验也很棒。 Clojure不是真正的Lisp,或者说它是Lisp家族的一部分,但是它具有额外的语法。它与JVM交互的能力使得轻松利用那里的数千个JVM库成为可能。

我很乐意再做一次,尽管我认为Common Lisp和CLOS及其模块系统使在大范围内进行编程变得容易一些。 Clojure使用spec探索了一些有趣的领域,因此很有趣的是,该语言将来会朝哪个方向发展。

这里的房间里还放着一只大象:Emacs Lisp! MacLisp的后代,编写起来非常有趣,而且Emacsitself是解释器,您对任何Elispcode都具有出色的自省性。 这些天我写的大多数Lisp可能都是Emacs Lisp。 cl-lib与Common Lisp非常接近,cl-lib为Common Lisp增添了足够的便利,使Elisp的写作非常愉快。 EIEIO添加了可以与cl-lib无缝使用的CLOS子集。 条件系统缺失。 我还做了相当多的Fennel,一种编译成Lua的Lisp。 我用它来写一个小游戏,写起来很有趣,因为您可以用aREPL开发游戏。 总而言之,Lisp的所有变体都是我在对计算机编程时获得的最有趣的体验。 Guile和Common Lisp绝对是我在Lisp中编程的最有趣的过程。