On Sep 1, 12:26 pm, [EMAIL PROTECTED] wrote:
> On Aug 31, 8:48 pm, Parth Malwankar <[EMAIL PROTECTED]> wrote:
>
>
>
> > Hello,
>
> > I have a situation in which different multi-methods
> > need similar behavior with different arguments.
>
> > So they call the same function (one-or-two below)
> > with the arguments. E.g.
>
> > (defmulti what-num (fn [x] x))
>
> > (defn one-or-two [x] (println "saw one or two: " x))
>
> > (defmethod what-num :one [x] (one-or-two x))
> > (defmethod what-num :two [x] (one-or-two x))
> > (defmethod what-num :three [x] (println "saw 3"))
> > (defmethod what-num :four [x] (println "saw 4"))
>
> > user=> (what-num :one)
> > saw one or two: :one
> > nil
> > user=> (what-num :two)
> > saw one or two: :two
> > nil
> > user=> (what-num :three)
> > saw 3
>
> > This works fine. However, I was wondering if its at all
> > possible to return duplication of creating the
> > methods 'what-num :one [x]' and 'what-num :two [x]'.
>
> > Can we have something to the effect of
> > 'what-num (or :one :two) [x]'? This would help get
> > rid of one-or-two and I would be able to define a single
> > what-num for this.
>
> > I could have 'defmulti what-num' conditionally return
> > something like :one-or-two but I am not sure if thats such
> > a good idea as I might end up with a big 'cond' over
> > time.
>
> > What would be a good way to do something like this?
>
> I don't know if it is a "good" way, but here is what I used for a
> similar problem:
>
> (defmacro defmethod-for-values
> [multifn dispatch-values-seq & fn-tail]
> `(let [pvar# (var ~multifn)
> method# (fn [EMAIL PROTECTED])]
> (doseq dispatch-val# ~dispatch-values-seq
> (. pvar# (commuteRoot (fn [#^clojure.lang.MultiFn mf#]
> (. mf#
> (assoc dispatch-val# method#))))))))
>
Thanks Darren.
Along the lines of your macro I created the one
below that avoids clojure.lang.*.
I keep forgetting this is lisp and we can write a macro :P
Here is what I could come up with.
(defmulti what-num (fn [x] x))
(defmacro defmethod-in [n dval-coll args & body]
(let [get-method (fn [d] `(defmethod ~n ~d ~args [EMAIL PROTECTED]))]
`(do ~@(map get-method dval-coll))))
(defmethod-in what-num [:one :two] [x] (println "1 or 2" x))
(defmethod what-num :three [x] (println "saw 3"))
(defmethod what-num :four [x] (println "saw 4"))
(defmethod what-num :default [x] :default)
In case this can be improved further, comments welcome.
Seems to be working fine so far:
user=> (what-num :four)
saw 4
nil
user=> (what-num :one)
1 or 2 :one
nil
user=> (what-num :two)
1 or 2 :two
nil
user=> (what-num :three)
saw 3
nil
user=> (what-num :five)
:default
Parth
> Which is just a wrapper around the defmethod macro that allows you to
> specify a list of values instead of a single value that will be mapped
> to the method.
>
> This would allow you to define your above example with:
>
> (defmulti what-num (fn [x] x))
>
> (defmethod-for-values what-num '(:one :two) [x] (println "saw one or
> two: " x))
> (defmethod what-num :three [x] (println "saw 3"))
> (defmethod what-num :four [x] (println "saw 4"))
>
> See this thread for more details:
>
> http://groups.google.com/group/clojure/browse_thread/thread/eed9015c2...
>
> Hope this helps,
> --Darren
--~--~---------~--~----~------------~-------~--~----~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---