This was my first thought as well, but we've got a name space
collision here. mb is referring to map as in IPersistentMap, not the
map function. mb's lazy-map is very similar to what you would get if
you memoized a function that took one parameter and then went into a
big case statement. ...if Clojure had a case statement.
--Chouser
I extended the implementation a bit. lazy-assoc and lazy-dissoc are also
available now. So for some use cases it should now be a simple drop-in
for the "normal" map. The rest of the interface like keys and merge and
such will (hopefully) follow soon.
The current version may be found at:
http://kotka.de/projects/clojure/lazy-map.html
Sincerely
Meikel
Very interesting.
Have you considered implementing this as a Java class derived from
IPersistentMap? I think using proxy would be sufficient (no need for
gen-class) then users could use the existing assoc, dissoc, and
keyword-function API for you lazy-map, just as we do already for
hash-maps and sorted-maps.
Just a thought.
--Chouser
Am 12.07.2008 um 23:57 schrieb Chouser:
> Very interesting.
And yesterday I noticed, that it doesn't really help me
in my specific problem. Argghh...
> Have you considered implementing this as a Java class derived from
> IPersistentMap? I think using proxy would be sufficient (no need for
> gen-class) then users could use the existing assoc, dissoc, and
> keyword-function API for you lazy-map, just as we do already for
> hash-maps and sorted-maps.
Hmmm... I have no clue about Java whatsoever. I had a
short look at it ten years ago and decided that it looked like
C without dirty tricks. So Scheme, Smalltalk and OCaml
looked more interesting (read "different").
In general for your idea: I will have a look at it. If I can just
use proxy w/o droping to Java itself, I will probably try it.
However there are some issues. assoc for example has
to be a macro since it must not evaluate the value. So
there will be at least the lazy-map and lazy-assoc macros.
dissoc, keys, merge, ... they should all basically work.
Let me see...
Sincerely
Meikel
the proxy implementation is ready. The lazy-map may be used now
as a complete drop-in replacement for the normal map. The only
gotcha, I found up to now, is that merge doesn't work, yet. However
find, keys, assoc, dissoc, etc. all work as with the normal map.
Value are only evaluated on access! Eg. find does not evaluate
the value! Calling val on the resulting MapEntry does.
For assoc: of course this works as the usual assoc, ie. a normal,
evaluated value is associated with the map. To associate a lazy
value one has to use lazy-assoc. By their nature lazy-assoc and
lazy-map are macros. Hence no apply et al...
Currently the implementation relies on a "feature" of proxy, which
qualifies as Dark Voodoo or Black Magic.
(def m (proxy [I] [] (foo [] :bar)))
Suppose the interface I does not support foo. Then (.foo m) gives
an exception, but (((proxy-mappings m) 'foo) this) gives :bar. This
is used to leak information out of the closure for the lazy-assoc.
Otherwise we cannot easily transfer non-evaluated values to
other maps.
The current version may be found at:
http://kotka.de/projects/clojure/lazy-map.html
Sincerely
Meikel