Skip to content

Instantly share code, notes, and snippets.

@fredokun
Created June 9, 2016 10:11
Show Gist options
  • Save fredokun/f1dc0a6a9ee343b7996965840c37cf4c to your computer and use it in GitHub Desktop.
Save fredokun/f1dc0a6a9ee343b7996965840c37cf4c to your computer and use it in GitHub Desktop.
Mutually recursive specs in clojure.spec
;;; Clojure 1.9 spec : an example of a mutually-recursive spec
(ns oddeven
(:require [clojure.spec :as s]))
(s/def ::zero #{:zero})
(s/def ::one #{:one})
(s/def ::succ #{:succ})
(s/def ::odd nil)
(s/def ::even (s/or :zero ::zero
:even (s/tuple ::succ ::odd)))
(s/def ::odd (s/tuple ::succ ::even))
(s/conform ::even :zero) ; zero is even
;; => [:zero :zero]
(s/conform ::even [:succ [:succ :zero]]) ; 2 is even
;; => [:even [:succ [:succ [:zero :zero]]]]
(s/conform ::odd [:succ :zero]) ; 1 is odd
;; => [:succ [:zero :zero]]
(s/conform ::odd [:succ [:succ :zero]]) ; 2 is not odd
;; => :clojure.spec/invalid
(s/explain ::odd [:succ [:succ :zero]]) ; (explanations...)
;; In: [1] val: [:succ :zero] fails spec: :typetheory.syntax/zero at: [1 :zero] predicate: #{:zero}
;; In: [1 1] val: :zero fails spec: :typetheory.syntax/odd at: [1 :even 1] predicate: vector?
;; => nil
(s/exercise ::even)
;; => generates 10 even numbers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment