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.

Reply via email to