Is there any way to invalidate this cache? Thanks, Ambrose
On Thu, Jan 30, 2014 at 9:35 PM, pron <ron.press...@gmail.com> 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 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. > -- 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.