Hi Ken,

I hadn't thought of using explicit metadata for this purpose, I guess
I was thinking that the class of the object would determine what it
could do.

Just working through this, if we take your example above, what if I
wanted to override the 'put' method rather than define a new one,
since we don't have access to 'proxy-super'.  For example making a map
that enforces storage of dates in a string format - something like:

(defprotocol DMap (put [this o1 o2]) (get-as-date [this o1]))

(extend-type clojure.lang.PersistentArrayMap
  NPut
  (put [this o1 o2] (if (::datestore (meta this)) (super put o1
(format-date-to-string o2)) (super put o1 o2)))
  (get-as-date [this o1] (if (::datestore (meta this)) (parse-date
(super get o1)) (super get o1)))

and get will return the string formatted version

or another example could be forcing all keys to be keywords, even if
they are provided as a string or symbol, without having to write
(assoc {} (keyword k) v) all the time.

the other motivation would be to be able to throw exceptions on
invalid input into a map or vector, rather than debugging involving
'why the hell has that map got an xxx in it!' when after much
searching it turns out i've got some function arguments around the
wrong way :)

Cheers,


- Lachlan


On 19 May 2011 11:17, Ken Wesson <kwess...@gmail.com> wrote:
> On Wed, May 18, 2011 at 7:19 PM, Lachlan <lachlan.kana...@gmail.com> wrote:
>> A further example of this proxy method not working would be trying to
>> add methods to a clojure.lang.PersistentVector.  It doesn't seem to
>> have an <init> ??
>
> => (seq (.getConstructors (type [])))
> nil
>
> PersistentVector lacks public constructors.
>
> => (filter #(.contains (str %) "static") (.getMethods (type [])))
> (#<Method public static clojure.lang.PersistentVector
> clojure.lang.PersistentVector.create(java.lang.Object[])>
>  #<Method public static clojure.lang.PersistentVector
> clojure.lang.PersistentVector.create(java.util.List)>
>  #<Method public static clojure.lang.PersistentVector
> clojure.lang.PersistentVector.create(clojure.lang.ISeq)>
>  #<Method public static java.lang.Object
> clojure.lang.AFn.applyToHelper(clojure.lang.IFn,clojure.lang.ISeq)
> throws java.lang.Exception>)
>
> It has what appear to be three static factory methods instead.
> Subclassing it seems unlikely to be possible.
>
>> Similarly, list is a problem.  The proxy method works when you provide
>> a value, but PersistentList$EmptyList does not.
>>
>> It seems to work nicely with clojure.lang.PersistentArrayMap, so this
>> kind of thing works
>>
>> (.dosomething (proxy [clojure.lang.PersistentArrayMap user.A] []
>> (dosomething [] (println (:akey this)))))
>> -> nil
>> (.dosomething (proxy [clojure.lang.PersistentArrayMap user.A]
>> [(into-array Object [:akey :aval])] (dosomething [] (println (:akey
>> this)))))
>> -> :aval
>>
>> ahh corners!
>
> Is there a reason not to just extend-type the type you're interested
> in? That is, why do you specifically want the protocol to work only
> with specially-created instances of String or PersistentVector or
> PersistentArrayMap, rather than extend it to those types and simply
> not use it for other instances?
>
> If you want to be able to distinguish the special instances at
> runtime, perhaps you'd be better off creating a wrapper object
> instead; or in the case of PersistentVector and PersistentArrayMap,
> using metadata to identify the special instances. You can even enforce
> it:
>
> (defprotocol Fooable
>  (foo [this]))
>
> (extend-type clojure.lang.PersistentArrayMap
>  Fooable
>  (foo [this]
>    (if (::fooable (meta this))
>      (println "fooed " this)
>      (throw (Error. "not fooable")))))
>
> (defn fooable-array-map [& args]
>  (with-meta
>    (apply array-map args)
>    {::fooable true}))
>
> user=> (foo (fooable-array-map :a 1 :b 2))
> "fooed {:a 1 :b 2}"
> nil
> user=> (foo (array-map :a 1 :b 2))
> #<CompilerException java.lang.Error not fooable (NO_SOURCE_FILE:0)>
> user=>
>
> --
> Protege: What is this seething mass of parentheses?!
> Master: Your father's Lisp REPL. This is the language of a true
> hacker. Not as clumsy or random as C++; a language for a more
> civilized age.
>
> --
> 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



-- 
J Lachlan Kanaley

M 0413 191 194
E lachlan.kana...@gmail.com

-- 
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

Reply via email to