anchor.diff:  (person-name 42)
   ;;=> java.lang.AssertionError: Assert failed: (s/valid? :my.domain/person person)
   
  -(person-name {::first-name "Elon" ::last-name "Musk" ::email "elon@example.com"})
  -;; Elon Musk
  +(person-name {::first-name "Bugs" ::last-name "Bunny" ::email "bugs@example.com"})
  +;; Bugs Bunny
   ----
   
   When the function is invoked with something that isn't valid `::person` data, the pre-condition fails. Similarly, if there was a bug in our code and the output was not a string, the post-condition would fail.
  
positive.code:           :opt-un [::phone]))
  
  (s/conform :unq/person
    {:first-name "Elon"
     :last-name "Musk"
     :email "elon@example.com"})
  ;;=> {:first-name "Elon", :last-name "Musk", :email "elon@example.com"}
  
  (s/explain :unq/person
    {:first-name "Elon"
     :last-name "Musk"
     :email "n/a"})
  ;; "n/a" - failed: (re-matches email-regex %) in: [:email] at: [:email] 
  ;;   spec: :my.domain/email-type
  
  (s/explain :unq/person
    {:first-name "Elon"})
  ;; {:first-name "Elon"} - failed: (contains? % :last-name) spec: :unq/person
  ;; {:first-name "Elon"} - failed: (contains? % :email) spec: :unq/person
  ----
  
  Unqualified keys can also be used to validate record attributes:
  
negative.code: [source,clojure]
  ----
  (s/valid? ::person
    {::first-name "Bugs"
     ::last-name "Bunny"
     ::email "bugs@example.com"})
  ;;=> true
  
  ;; Fails required key check
  (s/explain ::person
    {::first-name "Bugs"})
  ;; #:my.domain{:first-name "Bugs"} - failed: (contains? % :my.domain/last-name) 
  ;;   spec: :my.domain/person
  ;; #:my.domain{:first-name "Bugs"} - failed: (contains? % :my.domain/email)
  ;;   spec: :my.domain/person
  
  ;; Fails attribute conformance
  (s/explain ::person
    {::first-name "Bugs"
     ::last-name "Bunny"
     ::email "n/a"})
  ;; "n/a" - failed: (re-matches email-regex %) in: [:my.domain/email]
  ;;   at: [:my.domain/email] spec: :my.domain/email-type
  