此信息提供给熟悉Common Lisp或Scheme的程序员。
Clojure区分大小写
Clojure是Lisp-1
()
与nil不同
读取器没有副作用
关键字不是符号
符号不是存储位置(参见Var)
nil
不是符号
t
不是语法,请使用true
用户程序无法访问读取表
let
按顺序绑定
do
不是循环结构
没有尾调用优化,请使用recur
。
语法引号会解析符号,因此`x
与'x
不同。
`
具有自动生成符号功能。
~
是取消引号,,
是空格
存在用于映射、向量和集合的读取器语法
cons
、first
和rest
操作的是序列抽象,而不是具体的cons单元
大多数数据结构是不可变的
lambda是fn
,并支持根据元数重载
=
是相等谓词
全局Var可以动态重新绑定(如果声明为动态),而不会干扰词法局部绑定。不需要任何特殊声明来区分动态绑定和词法绑定。由于Clojure是Lisp-1,因此(全局)函数可以动态重新绑定(如果它们被标记为动态)。
没有letrec
、labels
或flet
- 使用(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 |