Clojure vs其他Lisps

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

我已经阅读了几本关于Clojure(Clojure 编程 , 实用Clojure , Clojure 的喜悦 ,以及Clojure在行动的Manning早期版本)的书籍,我认为这是一个很棒的语言。 我目前正在阅读主要处理Common Lispmacros的Let Over Lambda ,而且它也是一个非常有趣的语言。

不是一个Lisp专家(更多的是一个新手),但是这个语言家族让我着迷,一般情况下函数式编程也是如此。

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

  • 在JVM上运行。

    • JVM是一个非常稳定,高性能的语言环境,非常符合Sun的“一次编写,几乎任何地方运行”的梦想。 我可以在我的Macbook Pro上编写代码,将其编译为可执行的JAR文件,然后在Linux和Microsoft Windows上运行,只需进行一些额外的testing即可。

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

    • 标准,简单,multithreading模型。 Common Lisp是否有一个标准的multithreading包?

    • 虽然Common Lisp专家可能会告诉我,使用读取器macros,您可以将它们添加到CL中,以[]{}#{}分解所有括号中的单调。

Clojure的缺点

  • 在JVM上运行。
    • 没有尾recursion或延续。 Common Lisp支持连续性吗? 我相信计划需要两方面的支持。

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

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

  • 其他优点?

思考? 其他区别?

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

  • 在JVM上运行 – 因此可以自动访问JVM本身的奇妙工程(高级垃圾收集algorithm,HotSpot JIT优化等)

  • 非常好的Java互操作性 – 提供了与Java / JVM语言生态系统中大量库的兼容性。 我已经使用Clojure作为“胶水”语言来连接不同的Java库,效果很好。 由于我还开发了大量的Java代码,因此Clojure与Java工具很好地集成在一起(例如,我使用Maven,Eclipse和逆时针插件,用于我的Clojure开发)

  • 很好的语法向量[1 2 3] ,maps {:bob 10, :jane 15}并设置#{"a" "b" "c"} – 我认为这些非常重要的现代编程工具课程!)

  • 我个人喜欢使用方括号来绑定表单:例如(defn foo [ab] (+ ab)) – 我认为它使代码更清晰一些。

  • 强调懒惰的函数式编程,使用持久的,不可变的数据结构 – 尤其是所有核心的Clojure库都被devise为默认支持这个

  • 出色的STM实现多核并发。 我相信Clojure目前拥有任何语言的最佳并发故事(请参阅Rich Hickey自己的更详细的video )

  • 这是一个Lisp-1(就像Scheme),我个人比较喜欢(我认为在一个函数式语言中,保持函数和数据在同一个名字空间中是有意义的)

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

Common Lisp绝对支持函数式编程,但它也允许可变状态和命令式编程。

当然,函数式编程在并发和其他方面也有许多好处。 但是其他条件都是平等的,你也可以select你想要在每种情况下使用哪种方法。 Clojure并不完全禁止命令式编程,但与Common Lisp相比,它不太适应这种风格。

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

通常:

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

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

  • 大多数CL实现具有多任务function,库提供了一个通用接口

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

  • Common Lisp既不支持尾部呼叫优化,也不支持延续。 实施提供TCO和图书馆提供某种forms的延续。

这里有一个比较好的video(主要是球拍)和Clojure 。

公平的说,Racket也有数据types的语法糖(附加的阅读器)(#hash,#,方括号等)

另外,Clojure唯一的方法就是使用recur ,这是编译到JVM的缺点。

请注意, recur是Clojure中唯一的非堆栈消耗循环构造。 没有尾部呼叫优化,不鼓励使用自呼叫来循环未知边界。 recur是function性的,它在尾部位置的使用由编译器validation。 ( 特殊表格 )。