Schema 0.3.3 API documentation

Alternative Schema implementation. Clojure only at the moment.

stch.schema

A library for data shape definition and validation.
A Schema is just Clojure data, which can be used to
document and validate Clojure functions and data.

For example,

(def FooBar {:foo Keyword :bar [Number]}) ;; a schema

(check FooBar {:foo :k :bar [1.0 2.0 3.0]})
==> nil

representing successful validation, but the following
all return helpful errors describing how the provided
data fails to measure up to schema FooBar's standards.

(check FooBar {:bar [1.0 2.0 3.0]})
==> {:foo missing-required-key}

(check FooBar {:foo 1 :bar [1.0 2.0 3.0]})
==> {:foo (not (keyword? 1))}

(check FooBar {:foo :k :bar [1.0 2.0 3.0] :baz 1})
==> {:baz disallowed-key}

Schema lets you describe your leaf values using the
Any, Keyword, Number, String, and Int definitions below,
or (in Clojure) you can use arbitrary Java classes or
primitive casts to describe simple values.

From there, you can build up schemas for complex types
using Clojure syntax (map literals for maps, set literals
for sets, vector literals for sequences, with details
described below), plus helpers below that provide optional values,
enumerations, arbitrary predicates, and more.

Schema also provides macros for defining records with
schematized elements (defrecord'), and named or anonymous
functions (fn' and defn') with schematized inputs and
return values.  In addition to producing better-documented
records and functions, these macros allow you to retrieve
the schema associated with the defined record or function.
Moreover, functions include optional *validation*, which will throw
an error if the inputs or outputs do not match the provided schemas:

(defrecord' FooBar
  [foo :- Int
   bar :- String])

(defn' quux :- Int
  [foobar :- Foobar
   mogrifier :- Number]
  (* mogrifier (+ (:foo foobar) (Long/parseLong (:bar foobar)))))

(quux (FooBar. 10 "5") 2)
==> 30

(fn-schema quux)
==> (Fn Int [(Record user.FooBar {:foo Int, :bar java.lang.String}) java.lang.Number])

(with-fn-validation (quux (FooBar. 10.2 "5") 2))
==> Input to quux does not match schema: [(named {:foo (not (integer? 10.2))} foobar) nil]

As you can see, the preferred syntax for providing
type hints to schema's defrecord', fn', and defn' macros
is to follow each element, argument, or function name with a
:- schema.  Symbols without schemas default to a schema of Any.
In Clojure, class (e.g., java.lang.String) and primitive schemas
(long, double) are also propagated to tag metadata to ensure
you get the type hinting and primitive behavior you ask for.

If you don't like this style, standard Clojure-style
typehints are also supported:

(fn-schema (fn' [^String x]))
==> (Fn Any [java.lang.String])

You can directly type hint a symbol as a class, primitive,
protocol, or simple schema.  For complex schemas, due to Clojure's
rules about ^, you must enclose the schema in a {:s schema}
map like so:

(fn-schema (fn' [^{:s [String]} x]))
(Fn Any [java.lang.String])

(We highly prefer the :- syntax to this abomination, however.)
See the docstrings of defrecord', fn', and defn' for more
details about how to use these macros.

stch.schema.util

Private utilities used in schema implementation.