不純なクラス(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))))
これは機能しますが、シーケンスの先頭を保存しない場合に限ります。頭をキャプチャする変数を作成する場合:
(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)