仅当参数从上次调用更改时才执行函数体的函数/宏
Posted
技术标签:
【中文标题】仅当参数从上次调用更改时才执行函数体的函数/宏【英文标题】:Function/macro to execute function body only when arguments changed from last call 【发布时间】:2014-06-19 15:19:21 【问题描述】:这应该类似于memoize
,但非常不同。虽然 memoize 应该与纯函数一起使用,但它通常对加速 IO 相关函数很有用。
我正在寻找的函数/宏应该表现得像高阶函数。它产生的功能应该:
第一次调用时,它应该调用原始函数,并将参数传递给它 记住:参数,返回值 第二次调用时 使用相同的参数:它应该返回记忆的返回值 使用不同的参数:忘记最后一个参数和返回值,调用原始函数,记住当前参数和返回值 第 n 次调用时,始终将参数与上次调用进行比较,并按照上述方式进行操作。【问题讨论】:
这和 memoize 完全一样,只是它只记住一个参数->值对。 【参考方案1】:修改memoize
的源代码很容易做到这一点。
(defn memo-one [f]
(let [mem (atom )]
(fn [& args]
(if-let [e (find @mem args)]
(val e)
(let [ret (apply f args)]
(reset! mem args ret)
ret)))))
(defn foo [x] (println "called foo") x)
(def memo-foo (memo-one foo))
但是,已经有一个灵活的记忆库可以做到这一点。
(require '[clojure.core.memoize :as memo])
(defn foo [x] (println "called foo") x)
(def memo-foo (memo/lru foo :lru/threshold 1))
(memo-foo 1)
; called foo
; 1
(memo-foo 1)
; 1
(memo-foo 2)
; called foo
; 2
(memo-foo 1)
; called foo
; 1
【讨论】:
很好,特别是在值已被持有的情况下避免交换 我意识到我需要一些完全不同的东西(自定义缓存策略),但基本上我在实现之前就使用了它。额外的问题:比较类型化数组的快速、内存有效的方法 :)(是的,这些是我的论点,我将它们重用于性能)。 @skrat 我建议将您的奖励问题作为一个新问题提出,并详细说明您如何使用阵列。如果您要重用相同的数组,那么答案很简单。【参考方案2】:这是一个仅使用 clojure.core 的版本。我从 A. Webb 的示例中借用了foo
函数进行演示。
(defn memoize-1
[f]
(let [previous (atom nil)]
(fn [& args]
(second
(swap! previous
(fn [[prev-args prev-val :as prev]]
(if (and prev (= prev-args args))
prev
[args (apply f args)])))))))
user> (defn foo [x] (println "called foo") x)
#'user/foo
user> (def memo-foo (memoize-1 foo))
#'user/memo-foo
user> (memo-foo 1)
called foo
1
user> (memo-foo 1)
1
user> (memo-foo 2)
called foo
2
user> (memo-foo 1)
called foo
1
【讨论】:
以上是关于仅当参数从上次调用更改时才执行函数体的函数/宏的主要内容,如果未能解决你的问题,请参考以下文章