read


read
or learn more

Unk

Jun 20, 2011

unk is a memoization library for Clojure that provides an extension to the base capabilities.

Using unk

unk is easy to use.

Leiningen

[unk "0.9.0"]

Maven

<dependency>
  <groupId>unk</groupId>
  <artifactId>unk</artifactId>
  <version>0.9.0</version>
</dependency>

Source

Unk is on the Githubs.

Straight-up replacement

unk can be used in place of clojure.core.memoize.

(def slowly (fn [x] (Thread/sleep 3000) x)) 
(time [(slowly 9) (slowly 9)])
; "Elapsed time: 6000.63 msecs" 
;=> [9 9]

This calls for fogus.unk.memo:

(def sometimes-slowly (manipulable-memoize slowly)) 
(time [(sometimes-slowly 108) (sometimes-slowly 108)]) 
; "Elapsed time: 3000.409 msecs" 
;=> [108 108]

fogus.unk.memo is a raw replacement for clojure.core.memoize — it does the exact same thing. All of unk’s memoization strategies can operate as replacements for memoize, except that each displays its own operational characteristics.

Fifo

There is a basic Fifo cache.

(def id (memo-fifo identity 2))

This creates a new function id operating with a First-in-first-out cache of size two. How would this operate under use?

(id 42)
;=> 42

What does the cache look like?

(snapshot id)
;=> {[42] 42}

Simple enough. But what if we cross the size limit?

(id 108)
;=> 108
(id 9)
;=> 9
(snapshot id)
;=> {[108] 108, [9] 9}

Of course, the first entry in the cache 42 has been removed.

And the rest…

unk also provides a Least-recently-used (LRU), Least-used (LU), Time-to-live (TTL, in ms), and a basic cache (i.e. like memo) built on soft references.1. I will not go into incredible detail about those here, but I am working on documentation that will explain more and include more thorough usage scenarios.

Why unk?

Because I needed it on a project. I didn’t simply need memoization. I needed pluggable (LRU, LU, TTL, FIFO, etc.), manipulable (memo-swap!, memo-clear!, memo-unwrap, etc.), extendable (build-memoizer), and inspect-able (snapshot, etc.) memoization. It’s as simple as that. I suspect you may need it too. This is why I’m announcing it now, rather than waiting until it’s fully documented.

For now you can view the annotated unk source code for some ideas.

The true story of unk

unk is inspired by section 12.4 in The Joy of Clojure which is in turn inspired by the memoization philosophy espoused by Christophe Grand, Eugen Dück, and Meikel Brandmeyer. In addition, I would like to thank Chas Emerick for his memoization based on SoftReferences. This project would be nothing2 without their original vision. Thanks gentlemen!

:F


  1. In alpha at the moment. Use with care. Patches welcomed. 

  2. Seriously… nothing… I never would have thought of this on my own. 

7 Comments, Comment or Ping

  1. You (or someone else over there at Relevance) might want to invalidate this JIRA ticket then. It won’t go into some form of contrib anyway. It was based on the original thread.

    Furthermore I’d like to mention cache-dot-clj, which is also based on the original thread and does similar things you needed.

  2. Hmm, I smell a composite here (cache + memoizer) – can you pull them apart? (I see the caches there, but they don’t implement any common map/lookup interfaces). FYI:

    http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html

    And LIRS support, maybe?

    http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.116.2184

  3. @Meikel

    I’m not sure that ticket needs to be invalidated since Unk is not a part of contrib. I am also aware of cache-dot.clj since it’s development occurred mostly in parallel with Unk (although it was called Keepsake back then). Different approaches built on the solid core. cache-dot.clj has had more eyes on it and likely has more use in production.

  4. @Rich,

    They are (in effect) pulled apart, the matter of making them separate libraries would be mostly mechanical. I would love to add the lookup interfaces, but time is fleeting at the moment.

    Thanks for the pointer to LIRS, I will read up on it ASAP.

  5. Sebastián Galkin

    Why is (< 0 ttl) a precondition for ttl-cache-factory? I think it makes sense to allow ttl=0, for instance, I’d use it set to 0 during testing. It’s a nice parameter which allows degrading to no cache when = 0.

  6. @paraseba

    Agreed. I will make the change post-haste. Thanks

  7. Sebastián Galkin

    @fogus great! I’ll put this to good use. Thanks

Reply to “Unk”