defmulti

clojure.core

  • (defmulti name docstring? attr-map? dispatch-fn & options)
Creates a new multimethod with the associated dispatch function.
The docstring and attribute-map are optional.

Options are key-value pairs and may be one of:
:default the default dispatch value, defaults to :default
:hierarchy the isa? hierarchy to use for dispatching
defaults to the global hierarchy

3 Examples top

  • (defmulti service-charge (fn [acct] [(account-level acct) (:tag acct)]))
    (defmethod service-charge [::acc/Basic ::acc/Checking]   [_] 25)
    (defmethod service-charge [::acc/Basic ::acc/Savings]    [_] 10)
    (defmethod service-charge [::acc/Premium ::acc/Account] [_] 0)
  • ;this example illustrates that the dispatch type
    ;does not have to be a symbol, but can be anything (in this case, it's a string)
    
    (defmulti greeting
      (fn[x] (x "language")))
    
    ;params is not used, so we could have used [_]
    (defmethod greeting "English" [params]
     "Hello!")
    
    (defmethod greeting "French" [params]
     "Bonjour!")
    
    ;;default handling
    (defmethod greeting :default [params]
     (throw (IllegalArgumentException. 
              (str "I don't know the " (params "language") " language"))))
    
    ;then can use this like this:
    (def english-map {"id" "1", "language" "English"})
    (def  french-map {"id" "2", "language" "French"})
    (def spanish-map {"id" "3", "language" "Spanish"})
    
    =>(greeting english-map)
    "Hello!"
    =>(greeting french-map)
    "Bounjour!"
    =>(greeting spanish-map)
     java.lang.IllegalArgumentException: I don't know the Spanish language
  • ;; Implementing factorial using multimethods Note that factorial-like function 
    ;; is best implemented using `recur` for enable tail-call optimization to avoid 
    ;; stack overflow error. This is a only a demonstration of clojure's multimethod
    
    ;; identity form returns the same value passed
    (defmulti factorial identity)
    
    (defmethod factorial 0 [_]  1)
    (defmethod factorial :default [num] 
        (* num (factorial (dec num))))
    
    (factorial 0) ; => 1
    (factorial 1) ; => 1
    (factorial 3) ; => 6
    (factorial 7) ; => 5040
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/core.clj:1567 top

(defmacro defmulti
  "Creates a new multimethod with the associated dispatch function.
  The docstring and attribute-map are optional.

  Options are key-value pairs and may be one of:
    :default    the default dispatch value, defaults to :default
    :hierarchy  the isa? hierarchy to use for dispatching
                defaults to the global hierarchy"
  {:arglists '([name docstring? attr-map? dispatch-fn & options])
   :added "1.0"}
  [mm-name & options]
  (let [docstring   (if (string? (first options))
                      (first options)
                      nil)
        options     (if (string? (first options))
                      (next options)
                      options)
        m           (if (map? (first options))
                      (first options)
                      {})
        options     (if (map? (first options))
                      (next options)
                      options)
        dispatch-fn (first options)
        options     (next options)
        m           (if docstring
                      (assoc m :doc docstring)
                      m)
        m           (if (meta mm-name)
                      (conj (meta mm-name) m)
                      m)]
    (when (= (count options) 1)
      (throw (Exception. "The syntax for defmulti has changed. Example: (defmulti name dispatch-fn :default dispatch-value)")))
    (let [options   (apply hash-map options)
          default   (get options :default :default)
          hierarchy (get options :hierarchy #'global-hierarchy)]
      (check-valid-options options :default :hierarchy)
      `(let [v# (def ~mm-name)]
         (when-not (and (.hasRoot v#) (instance? clojure.lang.MultiFn (deref v#)))
           (def ~(with-meta mm-name m)
                (new clojure.lang.MultiFn ~(name mm-name) ~dispatch-fn ~default ~hierarchy)))))))
Vars in clojure.core/defmulti:
Used in 0 other vars

Comments top

No comments for defmulti. Log in to add a comment.