Clojure

与其他Lisp语言的差异

此信息提供给熟悉Common Lisp或Scheme的程序员。

  • Clojure区分大小写

  • Clojure是Lisp-1

  • ()与nil不同

  • 读取器没有副作用

  • 关键字不是符号

  • 符号不是存储位置(参见Var)

  • nil不是符号

  • t不是语法,请使用true

  • 用户程序无法访问读取表

  • let按顺序绑定

  • do不是循环结构

  • 没有尾调用优化,请使用recur

  • 语法引号会解析符号,因此`x'x不同。

  • `具有自动生成符号功能。

  • ~是取消引号,,是空格

  • 存在用于映射、向量和集合的读取器语法

  • consfirstrest操作的是序列抽象,而不是具体的cons单元

  • 大多数数据结构是不可变的

  • lambda是fn,并支持根据元数重载

  • =是相等谓词

  • 全局Var可以动态重新绑定(如果声明为动态),而不会干扰词法局部绑定。不需要任何特殊声明来区分动态绑定和词法绑定。由于Clojure是Lisp-1,因此(全局)函数可以动态重新绑定(如果它们被标记为动态)。

  • 没有letreclabelsflet - 使用(fn name [args]…​)进行自引用,letfn进行相互引用。

  • 在Clojure中,nil表示“无”。它表示任何类型的值的缺失,并不特定于列表或序列。

  • 空集合与nil不同。Clojure不将nil'()等同起来。

  • false表示两个可能的布尔值之一,另一个是true

  • 集合不仅仅是列表。你可以拥有空集合的实例,其中一些有字面量支持([]{}())。因此,不存在哨兵空集合值。

  • 从Scheme的角度来看,nil可能最接近你对#f的理解。

  • Clojure中的一个主要区别是序列。序列不是特定的集合,尤其是它们不一定是具体的列表。当您请求一个空集合生成其元素的序列(通过调用seq)时,它会返回nil,表示“我无法生成”。当您请求一个序列的最后一个元素的rest时,它会返回另一个逻辑序列。您只能通过依次对它调用seq来判断该序列是否为空。这使得序列和序列协议能够惰性

  • 一些序列函数对应于Scheme和CL中的函数,这些函数仅操作对/cons(“列表”),并返回表示“空”列表的哨兵值('()nil)。Clojure的返回值不同,它们不会返回特定的空集合,而是返回另一个逻辑序列。一些序列函数在Scheme/CL中没有对应项,并映射到类似Haskell/ML的函数。其中一些函数返回无限序列或计算序列,在这种情况下,与Scheme/CL列表等具体数据结构的类比就很牵强了。

  • 区分集合/数据结构和序列/迭代很有帮助。在CL和Scheme中,它们是混杂的,而在Clojure中,它们是分开的。

Clojure Common Lisp Scheme Java

有nil吗?

nil - 表示“无”

nil - 表示false或空列表

-

null

有true吗?

true

-

#t

true(原始类型)

有false吗?

false

-

#f

false(原始类型)

条件语句区分

nil或false/ 其他任何值

nil/非nil

#f/非-#f

false/true

列表/序列库操作的是区别的具体类型吗?

否 - 序列抽象,具有多种集合实现

是 - cons和向量

是 - 对

否 - 迭代器抽象,具有多种集合实现

有单例空列表值吗?

否 - 可以拥有不同类型的空值

nil

'()

序列结束返回

一个逻辑序列,其seq返回nil

nil

'()

false

宿主null

nil

NA

NA

NA

宿主true

true(装箱)

NA

NA

NA

宿主false

false(装箱)

NA

NA

NA