Reputation: 317
I have a function which takes two inputs which I would like to memoize. The output of the function only depends on the value of the first input, the value of the second input has no functional effect on the outcome (but it may affect how long it takes to finish). Since I don't want the second parameter to affect the memoization I cannot use memoize
. Is there an idiomatic way to do this or will I just have to implement the memoization myself?
Upvotes: 1
Views: 702
Reputation: 1
You can use a custom memoize function. For example
(defn memoize-first [f]
(let [cache (atom {})]
(fn [x]
(if-let [cached-result (get @cache x)]
cached-result
(let [result (f x)]
(swap! cache assoc result)
result))))
(defn your-function []
;;
)
(def memoized-function (memoize-first your-function))
Upvotes: 0
Reputation: 43
Maybe you are not able to natively memoize those two arguments, but you could use partial
instead to take fewer than the normal arguments to your function. You won't be caching it's execution but that may be helpful if you need to pre-load some function parameters:
An example:
(defn sum [a b]
(+ a b))
(def partial-sum (partial sum 2))
(partial-sum 3) ;; returns 5
Upvotes: 0
Reputation: 34800
memoize
doesn't support caching only on some args, but's pretty easy to make it yourself:
(defn search* [a b]
(* a b))
(def search
(let [mem (atom {})]
(fn [a b]
(or (when-let [cached (get @mem a)]
(println "retrieved from cache")
cached)
(let [ret (search* a b)]
(println "storing in cache")
(swap! mem assoc a ret)
ret)))))
Upvotes: 2
Reputation: 16194
I'd recommend using a cache (like clojure.core.cache) for this instead of function memoization:
(defonce result-cache
(atom (cache/fifo-cache-factory {})))
(defn expensive-fun [n s]
(println "Sleeping" s)
(Thread/sleep s)
(* n n))
(defn cached-fun [n s]
(cache/lookup
(swap! result-cache
#(cache/through
(fn [k] (expensive-fun k s))
%
n))
n))
(cached-fun 111 500)
Sleeping 500
=> 12321
(cached-fun 111 600) ;; returns immediately regardless of 2nd arg
=> 12321
(cached-fun 123 600)
Sleeping 600
=> 15129
Upvotes: 2
Reputation: 51
You can wrap you function into another function (with one parameter) and call it the function with second default parameter. Then you can memoize the new function.
(defn foo
[param1]
(baz param1 default-value))
Upvotes: 0