Hi everybody, after playing around with protocols & datatypes, I found them very fun to use. Some questions: Performance I don't see (with my limited benchmarking) any significant difference between multifns and protocolfns:
user=> (defprotocol Test (protocol-fn [it] "Protocol-fn")) Test user=> (extend Object Test {:protocol-fn (fn [it] nil)}) nil user=> (defmulti multi-fn type) #'user/multi-fn user=> (defmethod multi-fn Object [it] nil) #<MultiFn clojure.lang.mult...@c8769b> user=> (defn simple-fn [it] nil) #'user/simple-fn user=> (dotimes [_ 10] (time (dotimes [_ 100000] (protocol-fn :it)))) "Elapsed time: 105.532562 msecs" "Elapsed time: 57.0031 msecs" "Elapsed time: 33.210602 msecs" "Elapsed time: 30.47827 msecs" "Elapsed time: 26.326202 msecs" "Elapsed time: 27.764654 msecs" "Elapsed time: 28.381284 msecs" "Elapsed time: 28.741735 msecs" "Elapsed time: 28.697525 msecs" "Elapsed time: 25.894514 msecs" user=> (dotimes [_ 10] (time (dotimes [_ 100000] (multi-fn :it)))) "Elapsed time: 372.338313 msecs" "Elapsed time: 73.104641 msecs" "Elapsed time: 58.832009 msecs" "Elapsed time: 60.312924 msecs" "Elapsed time: 58.626328 msecs" "Elapsed time: 57.005242 msecs" "Elapsed time: 54.493328 msecs" "Elapsed time: 56.283221 msecs" "Elapsed time: 54.575182 msecs" "Elapsed time: 54.939474 msecs" user=> (dotimes [_ 10] (time (dotimes [_ 100000] (simple-fn :it)))) "Elapsed time: 28.504607 msecs" "Elapsed time: 17.564177 msecs" "Elapsed time: 1.877194 msecs" "Elapsed time: 2.340661 msecs" "Elapsed time: 1.581906 msecs" "Elapsed time: 1.792407 msecs" "Elapsed time: 1.878591 msecs" "Elapsed time: 1.919937 msecs" "Elapsed time: 2.367759 msecs" "Elapsed time: 1.90555 msecs" This is what I have been expecting of course (Fn < Protocolfn < Multifn), but i was thinking that with Protocols dispatching would be significantly faster than with Multimethods. Am I missing something? Because they don't seem to provide the speed for implementing the core abstractions (like (seq <coll>)). Syntax With protocols you define the protocols using symbols and extend types by using the keywordized name eg. (defprotocol Test (protocol-fn [it] "Protocol-fn")) (extend Object Test {:protocol-fn (fn [it] nil)}) i understand that extend is a function and evaluates its arguments, and that {:protocol-fn (fn [it] nil)} is a real map, but wouldn't it be possible just to use a {<generic-fn> <new-method-fn>} map instead? The protocol should know its generic functions, so that wouldn't be ambiguous. {protocol-fn (fn [it] nil)}) ; seems a lot clearer to me Extensibility I've noticed that extending a protocol-fn redefines it: (def old-fn protocol-fn) ; from above (extend Number Test {:protocol-fn (fn [it] :a-number)}) (def new-fn protocol-fn) (= old-fn new-fn) false this worries me, because the semantics are differing from MultiFns and are less dynamic. Especially coupled with dynamic development this could lead to some gotchas. Clojure 1.1.0-alpha-SNAPSHOT user=> (defprotocol Test (prtcfn [it])) Test user=> (extend Object Test {:prtcfn (fn [it] :object)}) nil user=> (prtcfn (Object.)) :object user=> (def old-fn prtcfn) #'user/old-fn user=> (old-fn (Object.)) :object user=> (extend Number Test {:prtcfn (fn [it] :number)}) nil user=> (prtcfn (Object.)) :object user=> (prtcfn 1) :number user=> (def new-fn prtcfn) #'user/new-fn user=> (new-fn 1) :number user=> (old-fn 1) :object When some protocol-fns get bound in a closure this could hurt a lot. Sorry if this seems like nitpicking, but this is just what I noticed while experimenting -- 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