vie*_*bel 5 clojure clojurescript core.async
我想memoize用于使用core.async和<!例如的功能
(defn foo [x]
(go
(<! (timeout 2000))
(* 2 x)))
Run Code Online (Sandbox Code Playgroud)
(在现实生活中,为了缓存服务器调用的结果可能很有用)
我能够通过编写 memoize 的 core.async 版本(几乎与 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))))))
Run Code Online (Sandbox Code Playgroud)
用法示例:
(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
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更简单的方法来实现相同的结果。
**备注:我需要一个适用于<!. 对于<!!,请参阅此问题:如何记忆使用 core.async 和阻塞通道读取的函数?**
您可以使用内置的 memoize 函数来实现此目的。首先定义一个从通道读取并返回值的方法:
(defn wait-for [ch]
(<!! ch))
Run Code Online (Sandbox Code Playgroud)
请注意,我们将使用<!!and 不是<!因为我们需要此功能块,直到在所有情况下通道上都有数据为止。 <!仅当在 go 块内的表单中使用时才会表现出此行为。
然后,您可以通过将此函数与 组合来构造您的记忆函数foo,如下所示:
(def foo-memo (memoize (comp wait-for foo)))
Run Code Online (Sandbox Code Playgroud)
foo返回一个通道,因此wait-for将阻塞直到该通道有一个值(即直到内部操作foo完成)。
foo-memo可以类似于上面的示例使用,但您不需要调用,<!因为wait-for它将为您阻塞:
(go (println (foo-memo 3))
Run Code Online (Sandbox Code Playgroud)
您还可以在 go 块之外调用它,它的行为就像您期望的那样(即阻塞调用线程直到 foo 返回)。
| 归档时间: |
|
| 查看次数: |
513 次 |
| 最近记录: |