seq和列表之间的差异

时间:2014-03-14 21:51:26

标签: list clojure sequence seq

Clojure语言中seqs和list之间的区别是什么?

(list [1 2 3]) => ([1 2 3])
(seq [1 2 3]) => ([1 2 3])

这两种形式似乎被评估为相同的结果。

3 个答案:

答案 0 :(得分:13)

首先,它们似乎是相同的,但它们不是:

(class (list [1 2 3])) => clojure.lang.PersistentList
(class (seq [1 2 3])) => clojure.lang.PersistentVector$ChunkedSeq

list通常是一种实现,而seq始终是一种抽象。

seqs和list之间的区别在于以下三个方面,如 Clojure Programming

中所述

1。获得seq的长度可以是costy:

e.g。来自 Clojure Programming

(let [s (range 1e6)]
  (time (count s))) => 1000000
; "Elapsed time: 147.661 msecs"

(let [s (apply list (range 1e6))]
  (time (count s))) => 1000000
; "Elapsed time: 0.03 msecs

因为列表总是保存自己长度的记录,所以计算列表的操作需要花费不变的时间。但是,seq需要遍历自己以检索其count

2。 seqs可以是懒惰的,而列表则不能。

 (class (range)) => clojure.lang.LazySeq
 (class (apply list (range))) ;cannot be evaluated
 ; "java.lang.OutOfMemoryError: GC overhead limit exceeded"

3。 seqs可以是无限的,因此是不可数的,而列表总是可数的。

此外,列表是他们自己的seqs(实现细节):

(class (seq '(1 2 3))) => clojure.lang.PersistentList

总是可以使用cons创建seq。请查看this post中有关consconj之间差异的更多信息。

答案 1 :(得分:7)

Lists是作为链表实现的集合数据结构。 (其他核心集合数据结构是向量,映射和集合。)

Sequences是一个列表抽象,可以应用于多种数据。将序列视为逻辑视图,可以按顺序遍历某些的元素。

列表是具体类型与抽象匹配的情况,因此列表实际上是一个序列。但是,有许多序列不是列表,而是一些其他实现作为另一个数据结构的视图(如clojure.lang.PersistentVector $ ChunkedSeq)。

如果仔细观察,核心库中的函数将分为集合函数(将集合作为第一个参数并返回相同类型的集合)和序列函数(它们采用" seqable&# 34;作为最后一个参数,将其转换为序列,执行其功能,并返回序列)。示例集合函数包括conjassoccountget等。示例序列函数为mapreduce,{{1}事实上,大多数核心库都是基于序列而不是特定的集合类型。

序列是将所有Clojure数据结构与核心库中的所有FP函数结合在一起的抽象。这种统一是Clojure代码的简洁性和可重用性的基础。

答案 2 :(得分:2)

继Albus Shin的回答......

列表是几种中的一种序列。你不能看到它们之间的任何区别,因为Clojure以相同的方式打印它们。这里有一些(有很好的衡量标准):

=> (map (juxt identity seq? type)
     [(range 1 4)
      (take 3 (iterate inc 1))
      (list 1 2 3)
      (conj (list 2 3) 1)
      (cons 1 (list 2 3))
      [1 2 3]
      (seq [1 2 3])])

产生......

([(1 2 3) true clojure.lang.LazySeq]
 [(1 2 3) true clojure.lang.LazySeq]
 [(1 2 3) true clojure.lang.PersistentList]
 [(1 2 3) true clojure.lang.PersistentList]
 [(1 2 3) true clojure.lang.Cons]
 [[1 2 3] false clojure.lang.PersistentVector]
 [(1 2 3) true clojure.lang.PersistentVector$ChunkedSeq])