Skip to content

Instantly share code, notes, and snippets.

@trevorc
Created March 15, 2012 07:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trevorc/2042755 to your computer and use it in GitHub Desktop.
Save trevorc/2042755 to your computer and use it in GitHub Desktop.
Persistent Ring Buffer
(ns com.caira.util.ringbuffer
(:import (clojure.lang Counted IPersistentCollection IPersistentVector
Indexed RT SeqIterator Seqable Util)
(java.util Collection List)))
(defn ^:private iterables-equiv? [^Iterable i1 ^Iterable i2]
(let [it1 (.iterator i1)
it2 (.iterator i2)]
(loop []
(or (not (.hasNext it1))
(when (clojure.lang.Util/equiv (.next it1) (.next it2))
(recur))
false))))
(deftype PersistentRingBuffer [^int offset ^int capacity
^IPersistentVector v]
Collection
List
(contains [_ o] (.contains v o))
(containsAll [_ c] (.containsAll v c))
(get [this index] (.nth this index))
(isEmpty [_] (empty? v))
(iterator [this] (SeqIterator. (.seq this)))
(size [_] (.count v))
(toArray [this] (RT/seqToArray (.seq this)))
Seqable
(seq [_]
(seq (concat (drop offset v) (take offset v))))
Counted
IPersistentCollection
(count [this] (count v))
(cons [this o]
(PersistentRingBuffer.
(mod (inc offset) capacity)
capacity
(if (= offset (.count this))
(conj v o)
(assoc v offset o))))
(empty [_] (PersistentRingBuffer. 0 capacity []))
(equiv [this o]
(and (instance? List o)
(= (.count this) (.count o))
(iterables-equiv? this o)))
Indexed
(nth [_ ^int i]
(when (>= i capacity)
(throw (IndexOutOfBoundsException.)))
(nth v (mod (+ i offset) capacity)))
(nth [this ^int i ^Object not-found]
(if (and (>= i 0)
(< i (.count this)))
(.nth this)
not-found)))
(defn ring-buffer [size]
(PersistentRingBuffer. 0 size []))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment