Skip to content
Brian Marick edited this page Mar 13, 2016 · 8 revisions

Note: updated to 2.0

The structural-typing.type namespace contains both functions that create types and also those that check them. That's convenient for examples and playing around at the repl. In your code, I recommend you isolate type creation in one namespace, create in it checking functions that hide the type repo, and require that namespace in all the rest of your code.

Here is a simple example. For variety, the type-repo is changed so that it throws an exception on error, rather than printing the error explanation to standard error.

(ns definition
  "An example of creating your own type namespace"
  ;; Because this is all about tailoring structural-typing, the rare `:refer :all` is appropriate:
  (:use structural-typing.type)
  ;; Additional predefined predicates live here:
  (:require [structural-typing.preds :as pred])
  ;; They're not actually used in this example.
  )

(def type-repo
  (-> empty-type-repo
      (replace-error-handler throwing-error-handler)

      (named :Point
             (requires :x :y)
             {:x integer? :y integer?})))

Other namespaces could use this type repo as follows:

  (ns myapp.user
    (:require [structural-typing.type :as type]
              [myapp.mytypes :as mytypes]))
  ...
  (type/built-like mytypes/type-repo :Point ok)

That's pretty awkward:

  1. Requiring two namespaces to make use of one idea (checking my types)?
  2. There are two entities - the namespace and the type repo - that really stand in for the same idea.

Instead, we arrange for modified versions of all the usual type-checking functions to be exported from mytypes, by adding this to its end:

(ensure-standard-functions type-repo)

Now other namespaces can do all of the following:

  (ns myapp.user
    (:require [myapp.mytypes :as mytypes]))
  
  (def ok {:x 1 :y 1})
  (mytypes/built-like? :Point ok)

  (mytypes/built-like :Point ok)
  (mytypes/<>built-like ok :Point)

  (mytypes/all-built-like :Point [ok ok])
  (mytypes/<>all-built-like [ok ok] :Point)