Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Last active September 29, 2016 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olivergeorge/9d822447e4838092d07138ea51af5782 to your computer and use it in GitHub Desktop.
Save olivergeorge/9d822447e4838092d07138ea51af5782 to your computer and use it in GitHub Desktop.
(ns devcards-vs-clojure-spec.code-as-data
(:require [clojure.spec :as s]))
; detect the "pull-spec type" associated with a spec
(defmulti pull-type* first)
(defn pull-type [spec]
(when (seq? spec)
(pull-type* spec)))
(defmethod pull-type* :default [_])
(defmethod pull-type* `s/keys [_] :map-spec)
(defmethod pull-type* `s/every [_] :pattern)
(defmethod pull-type* `s/and
[[_ & pred-forms]]
(some pull-type pred-forms))
; Translate the spec into a pull-spec
(defmulti pull-step* first)
(defn pull-step [spec]
(when (seq? spec) (pull-step* spec)))
(defmethod pull-step* `s/keys
[[_ & {:keys [req req-un opt opt-un gen]}]]
(set (map (fn [k]
(let [f (s/form k)]
(if (pull-type f)
{(name k) (pull-step f)}
(name k))))
(concat req req-un opt opt-un gen))))
(defmethod pull-step* `s/every
[[_ pred & _]]
(let [f (s/form pred)]
(when (pull-type f)
(vec (pull-step f)))))
(defmethod pull-step* `s/and
[[_ & pred-forms]]
(mapcat pull-step* pred-forms))

AIM: Translate a clojure.spec form into what we call a "pull spec" which is based on graphql / datomic pull-api spec.

(s/def :props/PROJ_CONTACT
  (s/keys :req-un [:PROJ_CONTACT/NAME
                   :PROJ_CONTACT/PHONE
                   :PROJ_CONTACT/EMAIL]))

(s/def :props/PROJ_CATEGORY
  (s/keys :req-un [:PROJ_CATEGORY/CATEGORY_TITLE]))

(s/def :props/PROJ_CONTACTs
  (s/coll-of :props/PROJ_CONTACT))

(s/def :props/PROJ_PROJECT
  (s/keys :req-un [:PROJ_PROJECT/TITLE
                   :props/PROJ_CATEGORY
                   :PROJ_PROJECT/DESCRIPTION
                   :props/PROJ_CONTACTs]))

(clojure.pprint/pprint
  (pull-step (s/form :props/PROJ_PROJECT)))
#{"DESCRIPTION" "TITLE" {"PROJ_CONTACTs" ["NAME" "PHONE" "EMAIL"]}
  {"PROJ_CATEGORY" #{"CATEGORY_TITLE"}}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment