@clojurians.net in a hurry this morning, but wanted to let you know your instructions worked fabulously. Was especially delighted to learn about 'nilable'. The specs you made for Clojure.core are fabulous and fabulously instructive. (eg, empty? taught me how to use nilable.) Will report more soon!
@genekim Glad to hear that. When I get the clojure.core spec namespace to the point where it's instrumentable as a whole, I plan to extract it into a separate GitHub project, because right now it seems it's going under a bit – with most people probably not even knowing about it, the chance of contributions (including specs for third-party libraries) isn't very good.
I think that with enough interest we should be able to build a collection of specs for all kinds of projects very quickly and much more easily than with plain spec – just macroexpand-1 any one of the >fdefs for multi-arity functions with heterogenous return specs from ghostwheel.specs.clojure.core and imagine writing that by hand.
With all of this we are really close to being able to get granular and precise error messages for every type-wise incorrect internal or external function call during testing time without actually having to write/debug a single unit test, which really has been a weakness of dynamically typed languages in general. Exciting times!
And regarding the inline-specs-as-documentation thing – even though I've been writing Clojure for a few years now, just writing out the specs for clojure.core taught me quite a few things I didn't know as well.
In terms of exploring a codebase/API there's just no comparison between having succinct and precise types/specs which are actually verified at compile- or test time and thus guaranteed to be correct and match the code, and a loosely defined, vague, overly wordy description of the input and output which may or may not be up to date (and probably isn't).