Skip to content

Instantly share code, notes, and snippets.

@escherize

escherize/memo.clj

Created Apr 23, 2019
Embed
What would you like to do?
(ns scratch.memo)
(defn add-one-api-call [n]
(println "Getting Request for: " n)
(Thread/sleep 1000)
{:response (+ 1 n)})
(defn request [& ns]
(let [cached-api-call (memoize add-one-api-call)]
(mapv cached-api-call ns)))
;; notice below, we only request 1 Once:
(comment (time (request 1 2 3 1)))
;; Prints:
;; Getting Request for: 1
;; Getting Request for: 2
;; Getting Request for: 3
;; "Elapsed time: 3005.887448 msecs"
;;=> [{:response 2} {:response 3} {:response 4} {:response 2}]
;; but notice it takes over 3 seconds, and is synchronous, we can do
;; better... pmap can do that:
(defn request-2 [& ns]
(let [cached-api-call (memoize add-one-api-call)]
(vec (pmap cached-api-call ns))))
(time (request-2 1 2 3 1))
;; Prints:
;; Getting Request for: Getting Request for: Getting Request for: 123
;;
;;
;; Getting Request for: 1
;; "Elapsed time: 1002.294841 msecs"
;; If you have a keen eye, you'll notice even though we wrapped our
;; api call with memoization we failed to use it, since the response
;; for 1 didn't come back in time to fill in the cache for
;; cached-api-call.
;; So, let's ignore duplicates like this:
(defn request-3 [& ns]
(let [workers (mapv #(future [% (add-one-api-call %)]) (distinct ns))
n->result (into {} (mapv deref workers))]
(mapv n->result ns)))
;; Notice: 1 only printed once!
(time (request-3 1 2 3 1))
;; Prints:
;; Getting Request for: Getting Request for: 2
;; Getting Request for: 13
;;
;; "Elapsed time: 1001.408266 msecs"
;;=> [{:response 2} {:response 3} {:response 4} {:response 2}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.