ClojureSpec
ThoughtStorms Wiki
ClojureLanguage doesn't want types (RichHickey is AgainstTyping)
But it's useful to check a data structure against a schema. So Clojure's Spec is a schema checking library / language which can be used at runtime (as opposed to the CompileTime checking of static types.
Can be used for other tricks too, such as test-generation, and http://blog.cognitect.com/blog/2017/1/3/spec-destructuring
http://blog.fogus.me/2017/02/10/clojure-spec-data-design-01-sketching-a-struct/
http://blog.cognitect.com/blog/2016/12/9/works-on-my-machine-self-healing-code-with-clojurespec-1
Quora Answer : What is Clojure Spec, and what can you do with it?
Clojure is not a statically typed language.
Like Python, Javascript and Lisp. And unlike Java and Scala and ML / Haskell etc.
In statically typed languages, you say in your code that "this shape of data fits in that hole" (whether a variable or function argument etc.) and the compiler stops you putting the wrong shape of data in.
The Clojure compiler won't stop you. It will wait until you try to do something with the data that's the wrong shape and then blow up with a horribly verbose and unhelpful error message.
There are good reasons for that. Clojure was largely invented as a language for talking about data flexibly. Particularly to talk about data being put into and queried in a powerful database called Datomic that needed to handle data of different shapes.
So Rich Hickey decided he didn't want the shape of data to be fixed at compile time in Clojure. It needed to be flexible enough to adapt long after a module had been written, compiled and distributed.
At the same time, sometimes it's hell to track down a bug due to a complex bit of data not being the right shape that the functions that operate on it expect.
And sometimes you DO want the machine to be checking that for you, rather than you having to work out exactly how the data shape is different from the way its meant to be (usually by crawling around in the stack-trace when your program blows up)
So, we create libraries that can check whether a complex data structure actually accords to a "schema" which defines who the data structure is meant to be.
Unlike static types, these libraries are just code that executes at runtime.
Nevertheless, by using them, you can make sure that the data going into or coming out of a module or function is exactly the shape you want it to be.
However Hickey has another belief. That the usual way we think about schemas is wrong.
Usually, in both static typing and many dynamic schema checking systems we think that data has types in virtue of its context.
So, for example, (using a C-like notation), you tend to see something like this :
Person {
String name;
int telephone;
}
A Person is a name which is a string, and a telephone number which is an int.
Hickey doesn't like this because of reasons (possibly good ones, I haven't made up my mind yet).
He thinks that individual data items should be typed, outside of context.
So Hickey's schemas are like this :
String name;
int telephone;
Person { name, telephone };
Obviously, they don't really look like that, because that's C-flavoured pseudocode.
But you get the principle. name is String EVERYWHERE. And a telephone number is an int everywhere.
A Person is still made of a name and a telephone number.
Like I say, I don't have a good enough intuition as to whether Hickey is right that this is better. But
a) Hickey is a smart dude, and most of the design decisions he made for Clojure are pretty damned good
b) it's probably motivated by his focus on data and databases.
So, anyway. Spec is Hickey's standard Clojure library for writing schemas for checking data-structures.
It embodies that philosophy of types being absolute rather than context-dependent.
And it is a sophisticated "language" (DSL) for writing these "specs" (short for specification, but basically schemas). The language is like a "regular" language. In that you can write the equivalent of regexes ... eg. to say that
Person {name, telephone*}
to say that people can have any number of telephone numbers.
Because you have this powerful schema representation you can do more than just check existing data with it. You can generate new examples of data to use in tests. You can even generate unit-tests based on the specs.
Contrast :