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

Reply via email to