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 maptypes. 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
smime.p7s
Description: S/MIME cryptographic signature