Jos*_*osh 4 clojure lazy-sequences
我有一个LazySeq连接,在实现时创建.如果在尝试创建连接时发生异常,我想迭代已经在LazySeq中实现的所有连接并关闭它们.就像是:
(try
(dorun connections)
(catch ConnectException (close-connections connections)))
Run Code Online (Sandbox Code Playgroud)
虽然这close-connections会尝试再次实现连接,但这并不常用.我只想关闭已实现的连接,而不是实现其他连接.这样做的任何想法?
这会将先前实现的输入seq的初始片段作为向量返回:
(defn take-realized [xs]
(letfn [(lazy-seq? [xs]
(instance? clojure.lang.LazySeq xs))]
(loop [xs xs
out []]
(if (or (and (lazy-seq? xs) (not (realized? xs)))
(and (not (lazy-seq? xs)) (empty? xs)))
out
(recur (rest xs) (conj out (first xs)))))))
Run Code Online (Sandbox Code Playgroud)
在REPL进行测试:
(defn lazy-printer [n]
(lazy-seq
(when-not (zero? n)
(println n)
(cons n (lazy-printer (dec n))))))
(take-realized (lazy-printer 10))
;= []
(take-realized (let [xs (lazy-printer 10)] (dorun (take 1 xs)) xs))
;=> 10
;= [10]
;; range returns a lazy seq...
(take-realized (range 20))
;= []
;; ...wrapping a chunked seq
(take-realized (seq (range 40)))
;= [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
; 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
;; NB. *each* chunk of range gets its own LazySeq wrapper,
;; so that it is possible to work with infinite (or simply huge) ranges
Run Code Online (Sandbox Code Playgroud)
(;=>用于表示打印输出.)
realized?正如内森所建议的那样,确实是要走的路.然而,正如我在对Nathan的答案的评论中所解释的那样,还必须确保一个人不会无意中调用seq一个人的输入,因为这会导致输入序列的先前未实现的片段被实现.这意味着诸如non-empty和empty?之外的功能,因为它们是以实现的方式实现的seq.
(事实上,根本不可能在没有意识到的情况下判断懒惰的seq是否为空.)
此外,虽然类似lazify的函数对于非拆分序列很有用,但它们并不能阻止它们的底层序列以分块的方式实现; 相反,它们能够处理(层map,filter等)在一个unchunked方式操作即使在它们的原始输入seqs被分块.实际上,在实现这样的"lazified"/"unchunked"seq与其底层的,可能是chunked seq之间实际上没有任何联系.(实际上没有办法在输入序列的其他观察者面前建立这样的连接;没有其他观察者,它可以完成,但只是lazify以编写相当繁琐为代价.)