https://github.com/marick/structural-typing/
This is a validation or type-checking library for Clojure, playing in
roughly the same space as Prismatic Schema, Bouncer, or Validateur. It
was inspired by Elm's structural typing and my previous need to validate
complex data structures flowing into Clojure microservices.
Here is an example of a complex-ish type declaration. It could be made
more terse, but that wouldn't be useful as an example.
(type! :Line (requires :head :tail)
{:color [rgb-color? not-puce?]} ; optional by default
{:head (includes :Point)
:tail (includes :Point)})
(Note that `type!` mutates a "global type repo". That's nice for
examples, but there's a functional interface as well.)
----------
The most common question I'm asked is how this differs from Schema. Let
me immediately give you reasons to stop reading:
* Schema is roughly a superset (in terms of functionality)
* Schema supports Clojurescript, and this doesn't.
----------
If you're still here, I'll describe some of the differences in emphasis
that might make this library fit your needs. (Note, though, that I
haven't used Schema in a real project, so my claims about it might be
ignorant.)
Here are two expressions that do the same thing:
user=> (s/validate s/Keyword 42) ; Schema
ExceptionInfo Value does not match schema: (not (keyword? 42))
schema.core/validator/fn--1807 (core.clj:151)
user=> (t/built-like keyword? 42) ; Structural-typing
Value should be `keyword?`; it is `42`
=> nil
Several things can be seen here:
1. Schema takes a roughly conventional approach to typing (so-called
"nominal typing") in which (a) there are primitive types that are
"things", (b) complex types are built up from primitives, and (c) the
type system looks much like those that can be checked statically.
In my library, types are entirely about satisfying predicates. There is
not a "type" called Keyword; there's just Clojure's `keyword?`
predicate. (Note that, until someone solves the halting problem, this
throws away any hope that this type system could mesh with one that can
be statically checked.)
2. By default, a Structural-typing type failure prints a message to
standard output and returns nil. The reason for not throwing an
exception is that I love "pipeline" or "threaded" computation:
(-> structure
do-this
do-that)
Structural-typing is designed so that `built-like` can be tidily
inserted into such a threaded expression:
(some-> (built-like :MyType structure)
do-this
do-that)
(It's very likely that you'd override the default behavior to do
something other than `println`, but you'd still return `nil`. Or, if
you're monadically inclined, it's easy to make built-like return
`Either` values.)
3. I have an unnatural fondness for good error messages, so the default
error messages have been tweaked to be pleasing to the eye. They are
also customizable.
------------
If you've read this far, I'll refer you to the documentation rather than
explain more.
https://github.com/marick/structural-typing ; README
https://github.com/marick/structural-typing/wiki ; user guide
http://marick.github.io/structural-typing/ ; API
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.