Skip to content

Instantly share code, notes, and snippets.

@reborg
Last active February 7, 2018 13:28
Show Gist options
  • Select an option

  • Save reborg/05c709a2c0f640272a0d0b64ac75362f to your computer and use it in GitHub Desktop.

Select an option

Save reborg/05c709a2c0f640272a0d0b64ac75362f to your computer and use it in GitHub Desktop.

Revisions

  1. reborg revised this gist Feb 7, 2018. 1 changed file with 13 additions and 14 deletions.
    27 changes: 13 additions & 14 deletions runningdiff.clj
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    (when-let [s (seq xs)]
    (cons (assoc x :diff (if (seen id) (- value (seen id)) 0))
    (cons (assoc x :diff (- value (get seen id value)))
    (rdiff (rest s) (assoc seen id value)))))
    xs seen)))]
    (rdiff entries {}))
    @@ -28,24 +28,23 @@
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    (when x
    (cons (assoc x :diff (if (seen id) (- value (seen id)) 0))
    (cons (assoc x :diff (- value (get seen id value)))
    (rdiff c (assoc seen id value)))))
    (<!! c) seen)))]
    (rdiff (chan) {}))

    ;; The good thing of the xducer version is that it works idendepently from
    ;; the transport (as designed).
    (defn xdiff
    ([]
    (fn [rf]
    (let [seen (volatile! {})]
    (fn
    ([] (rf))
    ([result] (rf result))
    ([result {:keys [id value] :as x}]
    (let [diff (- value (get @seen id value))]
    (vswap! seen assoc id value)
    (rf result (assoc x :diff diff)))))))))
    ;; the transport (as per xducers design).
    (def xdiff
    (fn [rf]
    (let [seen (volatile! {})]
    (fn
    ([] (rf))
    ([result] (rf result))
    ([result {:keys [id value] :as x}]
    (let [diff (- value (get @seen id value))]
    (vswap! seen assoc id value)
    (rf result (assoc x :diff diff))))))))

    ;; (sequence (xdiff) entries)
    ;; ({:id 1, :value 88, :diff 0} {:id 2, :value 99, :diff 0} {:id 1, :value 98, :diff 10} {:id 3, :value 5, :diff 0} {:id 2, :value 100, :diff 1} {:id 3, :value 10, :diff 5} {:id 1, :value 150, :diff 52})
  2. reborg revised this gist Feb 7, 2018. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions runningdiff.clj
    Original file line number Diff line number Diff line change
    @@ -43,10 +43,9 @@
    ([] (rf))
    ([result] (rf result))
    ([result {:keys [id value] :as x}]
    (let [prev (get @seen id value)]
    (do
    (vswap! seen assoc id value)
    (rf result (assoc x :diff (- value prev)))))))))))
    (let [diff (- value (get @seen id value))]
    (vswap! seen assoc id value)
    (rf result (assoc x :diff diff)))))))))

    ;; (sequence (xdiff) entries)
    ;; ({:id 1, :value 88, :diff 0} {:id 2, :value 99, :diff 0} {:id 1, :value 98, :diff 10} {:id 3, :value 5, :diff 0} {:id 2, :value 100, :diff 1} {:id 3, :value 10, :diff 5} {:id 1, :value 150, :diff 52})
  3. reborg revised this gist Feb 7, 2018. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions runningdiff.clj
    Original file line number Diff line number Diff line change
    @@ -43,12 +43,10 @@
    ([] (rf))
    ([result] (rf result))
    ([result {:keys [id value] :as x}]
    (let [prev (@seen id)]
    (let [prev (get @seen id value)]
    (do
    (vswap! seen assoc id value)
    (rf result
    (assoc x :diff
    (if prev (- value prev) 0)))))))))))
    (rf result (assoc x :diff (- value prev)))))))))))

    ;; (sequence (xdiff) entries)
    ;; ({:id 1, :value 88, :diff 0} {:id 2, :value 99, :diff 0} {:id 1, :value 98, :diff 10} {:id 3, :value 5, :diff 0} {:id 2, :value 100, :diff 1} {:id 3, :value 10, :diff 5} {:id 1, :value 150, :diff 52})
  4. reborg revised this gist Feb 7, 2018. 1 changed file with 8 additions and 4 deletions.
    12 changes: 8 additions & 4 deletions runningdiff.clj
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    ;; different ways of producing the same running diff with lazy-seqs, core.async and transducers.
    ;; different ways of producing the same running diff with lazy-seqs, core.async or transducers.
    ;; the running diff injects a :diff key to each of the maps in the list. The :diff is the difference
    ;; between the current :value and the :value of the previously seen entry with the same :id.
    ;; it can be easily changed to process id-related items in a different way.

    (def entries [{:id 1 :value 88}
    {:id 2 :value 99}
    @@ -10,7 +11,8 @@
    {:id 3 :value 10}
    {:id 1 :value 150}])

    ;; standard lazy seqs
    ;; standard lazy seqs. Avoids atoms (or other state) by passing
    ;; the previously seen items each iteration.
    (letfn [(rdiff [xs seen]
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    @@ -20,7 +22,8 @@
    xs seen)))]
    (rdiff entries {}))

    ;; core.async version
    ;; core.async version is just a modification of the lazy seq version to pull
    ;; from a channel instead of (first xs).
    (letfn [(rdiff [c seen]
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    @@ -30,7 +33,8 @@
    (<!! c) seen)))]
    (rdiff (chan) {}))

    ;; xducer
    ;; The good thing of the xducer version is that it works idendepently from
    ;; the transport (as designed).
    (defn xdiff
    ([]
    (fn [rf]
  5. reborg created this gist Feb 7, 2018.
    50 changes: 50 additions & 0 deletions runningdiff.clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    ;; different ways of producing the same running diff with lazy-seqs, core.async and transducers.
    ;; the running diff injects a :diff key to each of the maps in the list. The :diff is the difference
    ;; between the current :value and the :value of the previously seen entry with the same :id.

    (def entries [{:id 1 :value 88}
    {:id 2 :value 99}
    {:id 1 :value 98}
    {:id 3 :value 5}
    {:id 2 :value 100}
    {:id 3 :value 10}
    {:id 1 :value 150}])

    ;; standard lazy seqs
    (letfn [(rdiff [xs seen]
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    (when-let [s (seq xs)]
    (cons (assoc x :diff (if (seen id) (- value (seen id)) 0))
    (rdiff (rest s) (assoc seen id value)))))
    xs seen)))]
    (rdiff entries {}))

    ;; core.async version
    (letfn [(rdiff [c seen]
    (lazy-seq
    ((fn [[{:keys [id value] :as x} :as xs] seen]
    (when x
    (cons (assoc x :diff (if (seen id) (- value (seen id)) 0))
    (rdiff c (assoc seen id value)))))
    (<!! c) seen)))]
    (rdiff (chan) {}))

    ;; xducer
    (defn xdiff
    ([]
    (fn [rf]
    (let [seen (volatile! {})]
    (fn
    ([] (rf))
    ([result] (rf result))
    ([result {:keys [id value] :as x}]
    (let [prev (@seen id)]
    (do
    (vswap! seen assoc id value)
    (rf result
    (assoc x :diff
    (if prev (- value prev) 0)))))))))))

    ;; (sequence (xdiff) entries)
    ;; ({:id 1, :value 88, :diff 0} {:id 2, :value 99, :diff 0} {:id 1, :value 98, :diff 10} {:id 3, :value 5, :diff 0} {:id 2, :value 100, :diff 1} {:id 3, :value 10, :diff 5} {:id 1, :value 150, :diff 52})