Here's the Javadoc<http://docs.oracle.com/javase/7/docs/api/java/lang/ClassValue.html> .
You can invalidate individual entries with the remove method. A class object itself - or at least those parts visible at runtime through reflection - can never change. Reloading a class with the same name (say, in a different ClassLoader) would result in a new ClassValue entry, as it should. If a class is GCed, its entry will be removed from the cache, as ClassValue uses WeakReferences for the keys. Note that ClassValue was added precisely with dynamic languages in mind, though it's very useful for other sophisticated uses of reflection, and is exactly intended to cache all sorts of dispatch mechanism. Here's the class description in the Javadoc: "Lazily associate a computed value with (potentially) every type. For example, if a dynamic language needs to construct a message dispatch table for each class encountered at a message send call site, it can use a ClassValue to cache information needed to perform the message send quickly, for each class encountered." On Thursday, January 30, 2014 4:40:31 PM UTC+2, Ambrose Bonnaire-Sergeant wrote: > > Is there any way to invalidate this cache? > > Thanks, > Ambrose > > > On Thu, Jan 30, 2014 at 9:35 PM, pron <ron.pr...@gmail.com > <javascript:>>wrote: > >> The bean function is a very useful Java interop feature that provides a >> read-only view of a Java Bean as a Clojure map. >> As it stands, the function performs introspection on the bean's class >> whenever the function is called: >> >> (defn bean >> "Takes a Java object and returns a read-only implementation of the >> >> map abstraction based upon its JavaBean properties." >> {:added "1.0"} >> >> [^Object x] >> (let [c (. x (getClass)) >> >> pmap (reduce1 (fn [m ^java.beans.PropertyDescriptor pd] >> >> (let [name (. pd (getName)) >> >> method (. pd (getReadMethod))] >> >> (if (and method (zero? (alength (. method >> (getParameterTypes))))) >> >> (assoc m (keyword name) (fn [] >> (clojure.lang.Reflector/prepRet (.getPropertyType pd) (. method (invoke x >> nil))))) >> >> m))) >> {} >> (seq (.. java.beans.Introspector >> >> (getBeanInfo c) >> >> >> (getPropertyDescriptors)))) >> v (fn [k] ((pmap k))) >> >> snapshot (fn [] >> (reduce1 (fn [m e] >> >> (assoc m (key e) ((val e)))) >> >> {} (seq pmap)))] >> >> >> (proxy [clojure.lang.APersistentMap] >> [] >> >> (containsKey [k] (contains? pmap k)) >> >> (entryAt [k] (when (contains? pmap k) (new clojure.lang.MapEntry k (v >> k)))) >> >> (valAt ([k] (when (contains? pmap k) (v k))) >> >> ([k default] (if (contains? pmap k) (v k) default))) >> >> (cons [m] (conj (snapshot) m)) >> >> (count [] (count pmap)) >> >> (assoc [k v] (assoc (snapshot) k v)) >> >> (without [k] (dissoc (snapshot) k)) >> >> (seq [] ((fn thisfn [plseq] >> >> (lazy-seq >> (when-let [pseq (seq plseq)] >> >> (cons (new clojure.lang.MapEntry (first pseq) (v (first >> pseq))) >> >> (thisfn (rest pseq)))))) (keys pmap)))))) >> >> >> >> >> I propose to cache the pmap value for each class using JDK 7's >> ClassValue<http://docs.oracle.com/javase/7/docs/api/>. >> Here's a proposed implementation: >> >> (def ^:private ^java.lang.ClassValue bean-class-value >> >> (proxy [java.lang.ClassValue] >> [] >> (computeValue [c] >> >> (reduce (fn [m ^java.beans.PropertyDescriptor pd] >> >> (let [name (. pd (getName)) >> >> method (. pd (getReadMethod)) >> >> type (.getPropertyType pd)] >> (if (and method (zero? (alength (. method >> (getParameterTypes))))) >> >> (assoc m (keyword name) (fn [x] >> (clojure.lang.Reflector/prepRet type (. method (invoke x nil))))) >> >> m))) >> {} >> (seq (.. java.beans.Introspector >> >> (getBeanInfo c) >> (getPropertyDescriptors))))))) >> >> >> (defn bean >> "Takes a Java object and returns a read-only implementation of the >> >> map abstraction based upon its JavaBean properties." >> {:added "1.0"} >> >> [^Object x] >> (let [c (. x (getClass)) >> >> pmap (.get bean-class-value c) >> >> v (fn [k] ((pmap k) x)) >> >> snapshot (fn [] >> (reduce (fn [m e] >> >> (assoc m (key e) ((val e) x))) >> >> {} (seq pmap)))] >> (proxy [clojure.lang.APersistentMap] >> >> [] >> (containsKey [k] (contains? pmap k)) >> >> (entryAt [k] (when (contains? pmap k) (new clojure.lang.MapEntry k (v >> k)))) >> >> (valAt ([k] (when (contains? pmap k) (v k))) >> >> ([k default] (if (contains? pmap k) (v k) default))) >> >> (cons [m] (conj (snapshot) m)) >> >> (count [] (count pmap)) >> (assoc [k v] (assoc (snapshot) k v)) >> >> (without [k] (dissoc (snapshot) k)) >> >> (seq [] ((fn thisfn [plseq] >> >> (lazy-seq >> (when-let [pseq (seq plseq)] >> >> (cons (new clojure.lang.MapEntry (first pseq) (v (first >> pseq))) >> >> (thisfn (rest pseq)))))) (keys pmap)))))) >> >> >> >> >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com<javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/groups/opt_out. >> > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.