Dear Clojurians,

I'd like to announce LazyMap2. LazyMap is to the map types, what
lazy-cons is to sequences.

- One may associate a value to a key in a lazy map by means of the
  lazy-assoc macro and the value does not get evaluated until it is
  accessed for the first time.

- One can turn the lazy map into a seq and conj its entries to another
  lazy map w/o evaluating the values. In particular this means one
  can even merge two lazy maps without evaluating the values.

- LazyMap works with *all* map types of Clojure. And creating a new
  lazy map with (empty ...) creates a new - empty obviously - lazy map
  of the same type.

- LazyMap supports meta data.

To summarise: LazyMap is a complete drop-in add-on to the built-in map
types. It provides lazy-* versions of the map constructors and lazy- assoc.
The rest works as for normal maps - contains?, keys, dissoc, ...

The source may be found at the usual place:
  http://kotka.de/projects/clojure/lazy-map.html

So much for the advertisement, but I also want to summarise shortly the
implementation. Although this is probably fairly obvious to OOP people,
I find some interesting aspects in it.

For Tcl there exists some kind of object system called "snit". The main
aspect of snit is that classes do not inherit from each other. Instead
snit provides a powerful interface to handle delegation. Ie. objects
are composed by other objects and method invokations are forwarded to
those objects and wrapped where necessary.

I'm not very experienced in industrial-strength OOP, but even I see that
using inheritance to implement LazyMap would obviously be a bad idea.
There are hash maps, sorted maps, ... and each would need its own lazy
version.

Whether a value gets evaluated before it is stored in the map or after
it is retrieved is completely orthogonal to the way the value is
actually stored in the map itself.

So all LazyMap does is to wrap around an arbitrary map and takes care,
that everything stored in the map is wrapped into a delay, which is
forced upon retrieval. So methods like entryAt and empty are caught and
modified as needed, while others like count can be simply forwarded to
the underlying map.

In this way one has one ring to rule them all. Ehm... one class to
handle them all. *coughcough*. Even when tomorrow there is a new type of
a map one can turn it into a lazy version, as long as it supports
IPersistentMap.

And this is again some very functional way of thinking: take small parts
and plumb them together...

So although this is nothing new - I think, BufferedWriter does something
similar - it is fun to see this in action. And again Clojure's macros
make it fit neatly into the system without much of a seam.

Clojure just doesn't stop being fun. :)

Sincerely
Meikel

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to