【问题标题】:Differences between a seq and a listseq 和 list 的区别
【发布时间】:2014-03-14 21:51:26
【问题描述】:

Clojure 语言中的 seq 和列表有什么区别?

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

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

【问题讨论】:

标签: list clojure sequence seq


【解决方案1】:

首先,它们可能看起来相同,但实际上并非如此:

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

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

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

1。获取 seq 的长度可能会很昂贵:

例如来自 Clojure 编程

(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 可以是无限的,因此是不可数的,而列表总是可数的。

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

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

人们总是可以使用cons 创建一个序列。查看this post 中的更多信息,了解consconj 之间的区别。

【讨论】:

  • 另外,PersistentList 是一个具体的数据类型,而ISeq 是一个接口。 (PersistentList 实现了ISeq,这就是为什么所有“seq”函数都在列表上工作的原因)。 Clojure.org 关于序列的页面将 seq 描述为“允许 [ing] 许多数据结构以序列的形式提供对其元素的访问”。请参阅here 了解更多信息。
  • IPersistentList 是“列表”实现的通用类的接口,其中PersistentList 是显而易见的接口(但也包括PersistentQueue)。
【解决方案2】:

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

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

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

如果仔细观察,核心库中的函数分为集合函数(将集合作为第一个参数并返回相同类型的集合)和序列函数(将“seqable”事物作为最后一个参数,将其转换为序列,执行它们的功能,并返回一个序列)。示例集合函数有conjassoccountget 等。示例序列函数有mapreducefilter 等。实际上,大多数核心库都工作在序列上,而不是特定的集合类型。

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

【讨论】:

    【解决方案3】:

    进一步了解 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])
    

    【讨论】:

      猜你喜欢
      • 2012-06-07
      • 2015-02-13
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-27
      • 2019-07-24
      相关资源
      最近更新 更多