Skip to content

Instantly share code, notes, and snippets.

@jimmyhmiller
Created July 19, 2018 18:36
Show Gist options
  • Save jimmyhmiller/1e5f4f200bf38e1d7f967272357bede2 to your computer and use it in GitHub Desktop.
Save jimmyhmiller/1e5f4f200bf38e1d7f967272357bede2 to your computer and use it in GitHub Desktop.
(require '[clojure.spec.alpha :as s]
'[clojure.set :as set]
'[clojure.spec.test.alpha :as stest])
(s/def ::thing any?)
(s/def ::other-thing any?)
(s/fdef a
:args (s/cat :map (s/keys :req [::thing]))
:ret (s/keys :req [::thing]))
(s/fdef b
:args (s/cat :map (s/keys :req [::thing]))
:ret (s/keys :req [::thing]))
(s/fdef c
:args (s/cat :map (s/keys :req [::thing
::other-thing])))
(defn a [map] map)
(defn b [map] map)
(defn c [map] map)
(defn get-fspec
"Provided a fully-qualified symbol, returns its retspec."
[fqsym]
(->> (rest (s/form fqsym))
(apply hash-map)))
(defn get-args-keys
"Hacky way to get args req keys.
Needs a better solution."
[spec]
(set (nth (nth (:args spec) 2) 2)))
(defn get-ret-keys
"Hacky way to get ret req keys.
Needs a better solution."
[spec]
(set (nth (:ret spec) 2)))
(defn compatible-step? [[fsym1 fsym2]]
(let [out (get-ret-keys (get-fspec fsym1))
in (get-args-keys (get-fspec fsym2))]
(set/subset? in out)))
(defn compatible-workflow? [steps]
(every? true? (map compatible-step? (partition 2 1 steps))))
(compatible-workflow? [`a `b]) ;; true
(compatible-workflow? [`a `b `c]) ;; false
(def workflow (comp c b a))
(stest/instrument [`a `b `c])
(workflow
{::thing 2})
;; fails
(workflow
{::thing 2
::other-thing 2})
;; succeeds despite workflows being incompatible
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment