Clojure与其他Lisps

Ral*_*lph 87 lisp comparison scheme clojure common-lisp

我的问题的目的不是要开始一场火焰战争,而是要确定在什么情况下每种语言都是"工作的最佳工具".

我已经阅读了几本关于Clojure的书(Clojure 编程,实用Clojure,Clojure 的喜悦,以及Clojure in Action的Manning Early Access版本),我认为这是一本很棒的语言.我目前正在阅读Let Over Lambda,它主要涉及Common Lisp宏,而且它也是一种非常有趣的语言.

不是 Lisp专家(更多的是新手),但这个语言系列对我来说很有吸引力,一般来说,功能编程也是如此.

Clojure的优点(以及"其他"的缺点):

  • 在JVM上运行.

    • JVM是一个非常稳定,高性能的语言环境,很好地满足了Sun的"一次编写,几乎在任何地方运行"的梦想.我可以在我的Macbook Pro上编写代码,将其编译成可执行的JAR文件,然后在Linux和Microsoft Windows上运行它,几乎不需要额外的测试.

    • (Hotspot和其他)JVM支持高质量的垃圾收集和非常高效的即时编译和优化.就在几年前,我写了一些必须在C中快速运行的东西,现在我毫不犹豫地在Java中这样做.

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

    • 打破了所有这些括号的单调[],{}#{},虽然Common Lisp的专家可能会告诉我,有读者宏,你可以添加那些CL.

Clojure的缺点:

  • 在JVM上运行.
    • 没有尾递归或延续.Common Lisp是否支持延续?我相信,计划需要支持两者.

其他人的优点(特别是Common Lisp)(以及Clojure的缺点):

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

  • 其他优点?

思考?其他差异?

mik*_*era 47

我喜欢Clojure到其他Lisps的个人原因列表(ps我仍然认为所有Lisps都很棒!):

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

  • 非常好的Java互操作性 - 提供与Java/JVM语言生态系统中大量库的兼容性.我使用Clojure作为"粘合"语言来连接不同的Java库,效果很好.由于我还开发了大量的Java代码,因此Clojure可以很好地与Java工具集成(例如,我使用Maven,Eclipse和Counterclockwise插件用于我的Clojure开发)

  • 矢量[1 2 3],地图{:bob 10, :jane 15}和集合的语法很好#{"a" "b" "c"}- 我认为这些是现代编程的必备工具(当然还有列表!)

  • 我个人喜欢使用方括号来绑定表单:例如(defn foo [a b] (+ a b))- 我认为它使代码更清晰易读.

  • 强调使用持久,不可变数据结构的惰性函数式编程 - 特别是所有核心Clojure库都设计为默认支持这一点

  • 针对多核并发的出色STM实现.我相信Clojure目前拥有任何语言的最佳并发故事(有关Rich Hickey本人的详细说明,请参阅此视频)

  • 这是一个Lisp-1(比如Scheme),我个人更喜欢(我认为在函数式语言中将函数和数据保存在同一个命名空间中是有意义的)

  • STM为+1.通过itselft,足以证明使用Clojure是合理的. (2认同)
  • 您仍然可以使用库CL-STM获取STM. (2认同)
  • @AndréCaron只在你需要的时候. (2认同)

Cha*_*ers 24

Clojure和Common Lisp之间的一个重要区别是Clojure对函数式编程更具说明性.Clojure的哲学,习语,以及某种程度上的语言/图书馆强烈鼓励并且有时坚持你以功能性方式编程(没有副作用,没有可变状态).

Common Lisp肯定支持函数式编程,但它也允许可变状态和命令式编程.

当然,在并发和其他方面,函数式编程有许多好处.但在其他条件相同的情况下,选择您想要针对每种情况使用哪种方法也是很好的.Clojure并没有完全禁止命令式编程,但它比Common Lisp更不适应这种风格.

  • @mikera:除了Clojure依赖于使用Java库之外,所有这些库都需要命令式,并且充满了副作用.我发现与Java的绑定是一个有毒的礼物...... (5认同)
  • @mikera:图书馆确实有一个好处.我只是指出使用Java库(这是Rich Hickey的语言主要目标之一)真的违背了Clojure的"功能性比其他lisps"更多的方面.我的意见旨在表示:"除非你重写/包装这些库,否则你将得到命令式的代码,并且不会受益于Clojure更好的部分". (4认同)
  • @Charlie Flowers:我相信在Common Lisp中,可以以"纯粹功能"的方式编程(持久数据结构支持等),但需要遵守规则.正确? (3认同)
  • 只是澄清"没有副作用,没有可变状态" - Clojure确实具有可变状态(refs,原子,代理等都是可变的)但要求你以受控方式访问它(即通过STM机制和相关的事务处理)更新语义) (2认同)
  • @Andre - 当然,如果您决定使用需要可变状态和命令式语义的库,那么您必须管理它。这与从任何其他语言访问此类库没有什么不同。但是你有两个不错的选择:a) 不要使用这样的库——你可以用纯 Clojure 编写完美的代码或者 b) 将与这些库接口的复杂性包装在一个很好的 Clojure 风格的函数式界面中,这通常很容易使用宏或代理等。总的来说,我发现利用 Java 库的能力比问题大得多。 (2认同)

Rai*_*wig 23

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

通常:

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

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

  • 大多数CL实现具有多任务处理能力,库提供通用接口

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

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


Dan*_*iil 10

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

公平地说,Racket也有数据类型的语法糖(额外的读者东西)(#hash,#,方括号等)

另外,Clojure唯一能够进行正确尾调用的方法就是使用recur,这是编译JVM的缺点.

注意,这recur是Clojure中唯一不占用堆栈的循环结构.没有尾调用优化,并且不鼓励使用自调用来循环未知边界.recur功能正常,它在尾部位置的使用由编译器验证.(特殊表格).

  • 链接死了(再次?) (6认同)