Clojure与其他Lips的比较[关闭]


93

我提出这个问题的目的不是发动一场火焰之战,而是确定每种语言在什么情况下是“从事这项工作的最佳工具”。

我已经阅读了几本有关Clojure的书(编程Clojure实用ClojureClojure 的喜悦以及Clojure in Action的Manning早期访问版),我认为它是一种很棒的语言。我目前正在阅读Let Over Lambda,它主要处理Common Lisp宏,它也是一种非常有趣的语言。

不是 Lisp专家(更多的是新手),但是这种语言家族和函数式编程一样,让我着迷。

Clojure的优点(和“其他”的缺点):

  • 在JVM上运行。

    • JVM是一种非常稳定的高性能语言环境,完全符合Sun的梦想:“编写一次,几乎可以在任何地方运行”。我可以在Macbook Pro上编写代码,将其编译为可执行的JAR文件,然后在不进行额外测试的情况下在Linux和Microsoft Windows上运行它。

    • (热点和其他)JVM支持高质量的垃圾收集以及非常高效的即时编译和优化。几年前,我编写了必须在C中快速运行的所有内容,而现在我毫不犹豫地在Java中这样做。

    • 标准,简单的多线程模型。Common Lisp是否具有标准的多线程程序包?

    • []{}和打破所有括号的单调性#{},尽管Common Lisp专家可能会告诉我,使用阅读器宏,您可以将其添加到CL中。

Clojure的缺点

  • 在JVM上运行。
    • 无尾递归或连续。Common Lisp是否支持延续?我认为,计划需要两者的支持。

他人的优点(尤其是Lisp的常见缺点(以及Clojure的缺点):

  • 用户可定义的阅读器宏。

  • 其他优势?

有什么想法吗?其他差异?


15
我个人喜欢一种括号;)看起来像“更干净”的代码
Moe

3
从我在“优势”列表上阅读的内容来看,您可能还喜欢Erlang www.erlang.org
Peer Stritzinger 2011年

4
Clojure确实通过“递归”特殊形式支持显式尾递归。如果您明确要求尾部递归,这将使您能够获得尾部递归的所有好处(唯一的例外是它当前不支持多个函数之间的相互尾部递归)。
米克拉2011年

1
Clojure至少在“延续传递风格”的意义上也支持延续。您是正确的,它没有一流的延续。参见stackoverflow.com/questions/1173133/continuations-in-clojure
mikera,2011年

@mikera:对一个函数进行尾递归。相互调用的两个函数必须通过“ trampolining”来完成,这有点令人费解(但以其自己的方式很优雅:-)。
拉尔夫

Answers:


52

我个人比较喜欢Clojure而不是其他Lips的原因的个人列表(ps,我仍然认为所有Lisps都很棒!):

  • 在JVM上运行-因此可以自动访问JVM本身的出色工程(高级垃圾收集算法,HotSpot JIT优化等)。

  • 很好的Java互操作性-提供与Java / JVM语言生态系统中各种库的兼容性。我使用Clojure作为一种“胶水”语言来连接不同的Java库,效果很好。由于我还开发了许多Java代码,因此Clojure与Java工具很好地集成在一起对我很有帮助(例如,对于Clojure开发,我使用Maven,Eclipse和Counterclockwise插件)

  • 矢量[1 2 3],映射{:bob 10, :jane 15}和集合的漂亮语法#{"a" "b" "c"}-我认为这些是现代编程中必不可少的工具(当然还有列表!)

  • 我个人喜欢将方括号用于绑定形式:例如(defn foo [a b] (+ a b))-我认为这使代码更易于阅读。

  • 强调具有持久性,不可变数据结构的惰性函数式编程-特别是所有核心Clojure库都默认情况下支持该功能

  • 出色的STM实现,可实现多核并发。我相信Clojure目前是所有语言中最好的并发故事(Rich Hickey自己详细介绍请参见此视频

  • 这是一个Lisp-1(例如Scheme),我个人更喜欢(我认为用功能语言将功能和数据保留在相同的名称空间中是有意义的)


2
STM +1。就其本身而言,足以证明使用Clojure是合理的。
安德烈·卡隆

2
您仍然可以使用库CL-STM获得STM。
Mike Manilone

2
@AndréCaron仅在需要时使用。
2015年

如果您想编写一个简单的webapp并将其托管在一个便宜的$ 5 /月的主机上,由于JVM,这显然对于Clojure是不可能的,对吗?
Hexatonic

@Hexatonic我不是很有经验,但是很难相信现在使用的机器没有JVM。
2016年

25

请记住,Clojure是一种语言和一种实现(通常在JVM上)。Common Lisp是一种具有十多种不同实现的语言。因此,我们这里存在类别不匹配的情况。例如,您可以将Clojure与SBCL进行比较。

通常:

  • JVM上运行Common Lisp的一个版本:ABCL

  • 大多数其他Common Lisp实现都没有

  • 大多数CL实现都具有多任务处理功能,一个库提供了一个通用接口

  • Common Lisp具有数组的语法。用户可以编写其他数据类型的语法,并由各种库提供。

  • Common Lisp既不支持尾部调用优化也不支持延续。实现提供TCO,而库提供某种形式的延续。


24

Clojure和Common Lisp之间的重要区别是Clojure对函数式编程更具规范性。Clojure的哲学,习语以及某种程度上的语言/库在很大程度上鼓励甚至坚持要求您以一种功能性的方式进行编程(无副作用,无可变状态)。

Common Lisp无疑支持功能编程,但它也允许可变状态和命令式编程。

当然,在并发和其他方面,函数式编程有很多好处。但是,在所有其他条件都相同的情况下,最好选择每种情况下要使用的方法。Clojure并没有完全禁止命令式编程,但是与Common Lisp相比,Clojure不太适合这种风格。


3
@Charlie Flowers:我相信在Common Lisp中可以以“纯功能”风格(持久数据结构支持等)进行编程,但是需要纪律。正确?
拉尔夫

2
只是澄清“没有副作用,没有可变状态”-Clojure确实具有可变状态(引用,原子,代理等都是可变状态),但是需要您以受控方式(即通过STM机制和相关的事务性方式)访问它更新语义)
mikera 2011年

5
@mikera:除了Clojure依赖于使用Java库才能使用,而且所有这些库都需要命令式样式,并且充满了副作用。我发现与Java绑定是一个中毒的礼物...
安德烈·卡伦

1
@Andre-当然,如果您决定使用需要可变状态和命令式语义的库,则必须进行管理。这与您从任何其他语言访问此类库没有什么不同。但是,您有两个不错的选择:a)不要使用此类库-您可以在纯Clojure中编写完美的代码,或者b)在一个不错的Clojure样式的功能接口中包装与这些库接口的复杂性,通常这很容易总体而言,我发现利用Java库的能力要比问题大得多。
mikera 2011年

4
@mikera:图书馆确实有好处。我只是指出,使用Java库(这是Rich Hickey语言的主要目标之一)确实违反了Clojure的“比其他方式更实用”的方面。我的评论意图是:“除非重写/包装这些库,否则您将获得命令式的代码,并且不会从Clojure的更好部分中受益”。
安德烈·卡隆

10

这是一个很好的视频,其中比较了Scheme(主要是Racket)和Clojure

公平地说,Racket也具有用于数据类型(#hash,#,方括号等)的语法糖(其他阅读器内容)。

另外,Clojure进行正确的尾部调用的唯一方法是使用recur,这是编译到JVM的缺点。

请注意,这recur是Clojure中唯一不消耗堆栈的循环构造。没有尾调用优化,不鼓励使用自调用循环未知范围。recur具有功能,并且在编译器中验证了其在尾部位置的使用。(特殊形式)。


我猜链接已经死了。
nawfal 2014年

1
@nawfal我想我已解决问题
Daniil

6
链接已失效(再次?)
扔掉帐户的时间

1
看起来该链接上的视频可以在这里找到:vimeo.com/22675078
GDP2 2016年

也有trampoline尾叫。
HappyFace
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.