8

我目前正在阅读 O'reilly Clojure 编程书,它在关于惰性序列的部分中有以下内容:

惰性序列有可能(尽管非常罕见)知道它的长度,因此将它作为 count 的结果返回,而不知道它的内容。

我的问题是,这是如何做到的,为什么它如此罕见?

不幸的是,本书在本节中没有具体说明这些内容。我个人认为在实现之前知道惰性序列的长度非常有用,例如,在同一页面中是使用函数处理的惰性文件序列的示例map。在实现序列之前知道可以处理多少个文件会很好。

4

2 回答 2

9

灵魂检查答案的启发,这里是一个固定大小集合上的昂贵函数的惰性但计数映射。

(defn foo [s f] 
  (let [c (count s), res (map f s)] 
    (reify 
      clojure.lang.ISeq 
        (seq [_] res) 
      clojure.lang.Counted 
        (count [_] c) 
      clojure.lang.IPending 
        (isRealized [_] (realized? res)))))


(def bar (foo (range 5) (fn [x] (Thread/sleep 1000) (inc x))))

(time (count bar))
;=> "Elapsed time: 0.016848 msecs"
;    5

(realized? bar)
;=> false


(time (into [] bar))
;=> "Elapsed time: 4996.398302 msecs"
;   [1 2 3 4 5]

(realized? bar)
;=> true

(time (into [] bar))
;=> "Elapsed time: 0.042735 msecs"
;   [1 2 3 4 5]
于 2013-08-27T18:08:33.540 回答
7

我想这是因为通常有其他方法可以找出大小。

我现在能想到的唯一可能做到这一点的序列实现,是某种昂贵的函数/过程在已知大小的集合上的映射。

一个简单的实现将返回底层集合的大小,同时将延迟序列的元素的实现(因此执行昂贵的部分)推迟到必要时。

在这种情况下,人们事先知道要映射的集合的大小,并且可以使用它来代替惰性序列大小。

有时它可能很方便,这就是为什么它不是不可能实现的原因,但我想很少有必要。

于 2013-08-27T17:32:57.807 回答