Skip to content

Instantly share code, notes, and snippets.

@bhb
Forked from mtnygard/multimethod_selector.clj
Last active November 13, 2019 10:22
Show Gist options
  • Save bhb/8ed99aff2d19d1be68b01b8ae12840c2 to your computer and use it in GitHub Desktop.
Save bhb/8ed99aff2d19d1be68b01b8ae12840c2 to your computer and use it in GitHub Desktop.
A clojure.spec.gen.alpha generator that picks a multimethod implementation from the known set.
(require '[clojure.spec.gen.alpha :as sgen])
;; original
(defn multimethod-selector
"Returns a generator that picks one dispatch value from the known
dispatch values of a multimethod. Defers the lookup of dispatch
values until sampling time, so any defmethods evaluated after the
generator is created may still be selected."
[s]
#(sgen/bind
(sgen/int)
(fn [i]
(let [ms (keys (methods s))]
(sgen/return (nth ms (mod i (count ms))))))))
;; (marginally) simpler?
(defn multimethod-selector2
"Returns a generator that picks one dispatch value from the known
dispatch values of a multimethod. Defers the lookup of dispatch
values until sampling time, so any defmethods evaluated after the
generator is created may still be selected."
[s]
#(sgen/bind
(sgen/return ::unused)
(fn [_]
(sgen/elements (keys (methods s))))))
(defmulti sound first)
(defmethod sound :dog [_] "woof")
(defmethod sound :cat [_] "meow")
(def gen ((multimethod-selector sound)))
(def gen2 ((multimethod-selector2 sound)))
(gen/sample gen) ;; (:cat :dog ...)
(gen/sample gen2) ;; (:cat :dog ...)
(defmethod sound :duck [_] "quack")
(gen/sample gen) ;; (:cat :duck :dog ...)
(gen/sample gen2) ;; (:cat :duck :dog ...)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment