A library for function memoization.
Why is there a need for another caching library? Motivation here.
With require as [memento.core :as m]
:
You can attach a cache to the function, by wraping it in a memo
call:
(def my-function
(m/memo #(* 2 %)))
This matches a basic memoize.
You can specify cache properties:
(def my-function
(m/memo {:size< 30 :ttl 40} #(* 2 %)))
This creates a Guava backed cache that is limited to 30 entries and entries expire after 40 seconds.
Read more about specifying properties HERE.
The default implementation is Guava based, and the supported properties are described HERE
You can add cache directly to a var:
(defn my-function [x] (* 2 x))
(m/memo {:size< 30 :ttl 40} #'my-function)
If you are using the same settings many times, simply use a variable.
; 1 day cache
(def long-cache {:ttl [1 :d]})
(m/memo long-cache #'my-function)
Normally cache only contains entries pertaining to one function. This presents a problem when you're trying to limit the size of the whole caching mechanism or when trying to invalidate large chunks of cached data in the system.
If you have a 100 cached functions, each with :size< 100
, you allow for 10000 cached items,
but one function might need 1000 items and another one might never need more than 10. In order
to make sizing easier, you can use a cache region.
A Region is a Cache that is shared between many functions and it is named (usually by a keyword).
You can specify that the function uses Region with id :my-region
as a cache like this:
(m/memo :my-region #'my-function)
This is equivalent to:
(m/memo {:region :my-region} #'my-function)
When using the map form, you can also specify key-fn
, ret-fn
, seed
.
If you specify a region that doesn't exist then no caching is done until the region is registered:
(set-region! :my-region {:size< 100})
All the functions caching into this region share the same limit of 100 entries.
See more info about regions HERE.
You define new regions that are active only within a scope (or alias an existing region).
This is extremely useful (and basically the main reason for this library), e.g.:
(m/memo {:region :request-scope} #'my-function)
(with-region :request-scope {}
; executes the code with all the :request-scope region functions being cached in a new
; region with spec `{}` (infinite cache)
...)
; drops all the cached values, as the region created for the scope is dropped
You can also redirect caching to an existing region with region aliasing:
; cache all functions that use :request-scope region in :small-cache region
(with-region-alias :request-scope :small-cache
....)
See more info about scopes and regions HERE.
If the wrapped function (or :ret-fn
post-processing hook) returns an object wrapped in
m/non-cached
function, then the result is not cached.
(def call-service
(m/memo
{:ttl 10}
(fn [....] ...
; don't cache error responses, but still return them
(if (<= 400 (:status resp)) (m/non-cached resp) resp))))
or more commonly via, the :ret-fn
(def call-service
(m/memo
{:ttl 10
:ret-fn #(if (<= 400 (:status %)) (m/non-cached %) %)}
(fn [....] ... resp)))
If you set -Dmemento.enabled=false
JVM option, then none of the caches will be used,
(though they will still exist, just empty).
You can manually evict entries:
; invalidate everything
(m/memo-clear! memoized-function)
; invaliate an arg-list
(m/memo-clear! memoized-function arg1 arg2 ...)
You can manually evict all entries in a region:
(m/memo-clear-region! :my-region)
You can add entries to a function's cache at any time:
(m/memo-add! memoized-function {[arg1 arg2] result})
(m/as-map memoized-function)
-> map of cache entries(m/region-as-map :my-region)
-> map of region's cache entries(m/memoized? a-function)
-> returns true if the function is memoized(m/memo-unwrap memoized-function)
-> returns memento.base/Cache
object on function if there is oneCopyright © 2020 Rok Lenarčič
Licensed under the term of the Eclipse Public License - v 2.0, see LICENSE.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close