How to memoize a function that uses core.async and lock channel?

I would like to use memoizefor a function that uses core.asyncand <!!eg

(defn foo [x]
  (go
    (<!! (timeout 2000))
    (* 2 x)))

(In real life, this can be useful for caching server call results)

I was able to achieve this by writing core.async version of memoize (almost the same code as memoize):

(defn memoize-async [f]
  (let [mem (atom {})]
    (fn [& args]
      (go
        (if-let [e (find @mem args)]
          (val e)
         (let [ret (<! (apply f args))]; this line differs from memoize [ret (apply f args)]
            (swap! mem assoc args ret)
            ret))))))

Usage example:

(def foo-memo (memoize-async foo))
(go (println (<!! (foo-memo 3)))); delay because of (<!! (timeout 2000))

(go (println (<!! (foo-memo 3)))); subsequent calls are memoized => no delay

I am wondering if there are simpler ways to achieve the same result.

Note. I need a solution that works with <!!. For <!see this question: How to memoize a function using the core.async channel and a non-blocking channel?

+1
source share
1 answer

memoize. , :

 (defn wait-for [ch]
      (<!! ch))

, <!!, <!, , . <! go.

memoized , foo, :

(def foo-memo (memoize (comp wait-for foo)))

foo , wait-for , (.. foo).

foo-memo , , <!!, wait-for :

(go (println (foo-memo 3))

go, , (.. , foo).

+4

Source: https://habr.com/ru/post/1548069/


All Articles