您可以将惰性序列包装在不纯类(如 java.util.concurrent.atomic.AtomicLong)周围以创建 id 序列:
(def id-counter (java.util.concurrent.atomic.AtomicLong.))
(defn id-gen []
(cons
(.getAndIncrement id-counter)
(lazy-seq
(id-gen))))
这有效,但前提是您不保存序列的头部。如果您创建一个捕获头部的 var:
(def id-seq (id-gen))
然后重复调用它,它会从序列的开头返回 id,因为你已经抓住了序列的头部:
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
(take 3 id-seq)
;; => (0 1 2)
但是,如果您重新创建序列,由于杂质,您将获得新的值:
(take 3 (id-gen))
;; (3 4 5)
(take 3 (id-gen))
;; (6 7 8)
(take 3 (id-gen))
;; (9 10 11)
我只建议出于教育目的(不是生产代码)执行以下操作,但您可以创建自己的 ISeq 实例,它更直接地实现杂质:
(def custom-seq
(reify clojure.lang.ISeq
(first [this] (.getAndIncrement id-counter))
(next [this] (.getAndIncrement id-counter))
(cons [this thing]
(cons thing this))
(more [this] (cons
(.getAndIncrement id-counter)
this))
(count [this] (throw (RuntimeException. "count: not supported")))
(empty [this] (throw (RuntimeException. "empty: not supported")))
(equiv [this obj] (throw (RuntimeException. "equiv: not supported")))
(seq [this] this)))
(take 3 custom-seq)
;; (12 13 14)
(take 3 custom-seq)
;; (15 16 17)