我正在学习Clojure中sequence
和nil
的概念。这是一个小实验的结果。
1:6 user=> (first '())
nil
1:7 user=> (rest '())
()
1:8 user=> (first (rest '()))
nil
这是否意味着'()实际上是一系列的nils?
答案 0 :(得分:10)
如果您想测试集合的“其余”是否为空,请使用next
。
user> (next '(foo bar))
(bar)
user> (next '())
nil
user> (doc next)
-------------------------
clojure.core/next
([coll])
Returns a seq of the items after the first. Calls seq on its
argument. If there are no more items, returns nil.
“nil-punning”(处理空集合/ seq和nil
同样的东西)去年被删除,有利于完全懒惰的序列。有关此更改的讨论,请参阅here。
答案 1 :(得分:4)
first
和rest
是适用于逻辑结构(seq
)的函数,而不是列表的链接cons结构(如在其他lisps中)。
Clojure根据序列(seqs)定义了许多算法。 seq是一个逻辑列表,与大多数Lisps不同,其中列表由具体的2槽结构表示,Clojure使用ISeq接口允许许多数据结构提供对其元素的序列访问。
行为是函数定义的结果,而不是由数据的原始结构决定的。
答案 2 :(得分:2)
否 - 空列表与无限的nils序列不同
这相对容易展示。假设我们有:
(def infinite-nils (repeat nil)) ; an infinite lazy sequence of nils
(def empty-list '()) ; an empty list
他们有不同数量的元素:
(count infinite-nils) => doesn't terminate
(count empty-list) => 0
取自他们:
(take 10 infinite-nils) => (nil nil nil nil nil nil nil nil nil nil)
(take 10 empty-list) => ()
如果你打电话给seq,你就得到了
(seq inifinite-nils) => sequence of infinite nils
(seq empty-list) => nil
通过理解以下事实可以在很大程度上解决原文中的混淆:
答案 3 :(得分:1)
还学习Clojure。
对于空sequences,rest
会返回seq
返回nil
的序列。
这就是你得到这种行为的原因。
我假设这是为了简化序列的递归,直到它们为空,并且可能是其他smartypants的原因......
答案 4 :(得分:0)
技术上是虽然不是有用的。
“通过调用(seq'(())创建的序列是否具有无限数量的空值?”
答案是肯定的,因为空序列的(休息)是一个空序列它自己可以有一个(休息)
顺便说一下,这个输出会产生误导:
1:7 user=> (rest '()) ()
这里的第一个'()是空列表 这里的secong()是空序列 序列的打印方式与repl中的列表相同,即使它们不相同。