    matcher key-matches-with-binding-clause-matcher
    binding key-matches-with-binding-clause-binding])
 
-(define-record-type
-  ^{:doc "A clause that matches the value of `key` of a map using `matcher`."}
-  KeyMatchesWithoutBindingClause
-  (make-key-matches-without-binding-clause key matcher)
-  key-matches-without-binding-clause?
-  [key key-matches-without-binding-clause-key
-   matcher key-matches-without-binding-clause-matcher])
+(defn key-matches-without-binding-clause
+  "Returns a clause that matches a `key` with a certain `matcher`."
+  [key matcher]
+  {:pre [(matcher? matcher)]}
+  (make-key-matches-without-binding-clause key matcher))
 
 (defn key-matches-with-binding-clause
   "Returns a clause that matches a `key` with a certain `matcher`, binding the

        `({~key ~'_} :guard ~(match-value message [key]))
        `{~key ~(match-value message [key])}))

    (key-matches-without-binding-clause? clause)
    (let [key         (key-matches-without-binding-clause-key clause)
          matcher     (key-matches-without-binding-clause-matcher clause)
          match-value (matcher->value matcher)]
      (if (predicate-matcher? matcher)
        `({~key ~'_} :guard ~(match-value message [key]))
        `{~key ~(match-value message [key])}))

    (path-matches-with-binding-clause? clause)
    (let [path        (path-matches-with-binding-clause-path clause)

    nil))

;;    There are four kinds of clauses
;; 1. Assert the existence of a value in a map for a key.
;;    - without binding - with binding
;; 2. Assert the existence of a value in a map for a path.
;;    - without binding - with binding
;; 3. Match a key in a map to some specific value.
;;    - without binding - with binding
;; 4. Match the value at a path in a map to a specific value.
;;    - without binding - with binding
;; 5. An optional clause that contains a regular clause and makes the match optional.

;; 1.
(define-record-type KeyExistsWithoutBindingClause
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`."}
  (make-key-exists-without-binding-clause key matcher)
  key-exists-without-binding-clause?
  [key key-exists-without-binding-clause-key
   matcher key-exists-without-binding-clause-matcher])

(define-record-type KeyExistsWithBindingClause
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `key`. When evaluated, binds it's result to `binding`."}
  (make-key-exists-with-binding-clause key matcher binding)
  key-exists-with-binding-clause?
  [key key-exists-with-binding-clause-key
   matcher key-exists-with-binding-clause-matcher
   binding key-exists-with-binding-clause-binding])

(defn key-exists-without-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [key]
  (make-key-exists-without-binding-clause key the-existence-matcher))

(defn key-exists-with-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [key bind]
  (make-key-exists-with-binding-clause key the-existence-matcher bind))

;; 2.
(define-record-type
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`."}
  PathExistsWithoutBindingClause
  (make-path-exists-without-binding-clause path matcher)
  path-exists-without-binding-clause?
  [path path-exists-without-binding-clause-path
   matcher path-exists-without-binding-clause-matcher])

(define-record-type
  ^{:doc "A clause that asserts the existence of a non-nil value in a map at the `path`. When evaluated, binds it's result to `binding`."}
  PathExistsWithBindingClause
  (make-path-exists-with-binding-clause path matcher binding)
  path-exists-with-binding-clause?
  [path path-exists-with-binding-clause-path
   matcher path-exists-with-binding-clause-matcher
   binding path-exists-with-binding-clause-binding])

(defn path-exists-with-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [path bind]
  (make-path-exists-with-binding-clause path the-existence-matcher bind))

(defn path-exists-without-binding-clause
  "Returns a clause that asserts the existence of a non-nil value at `key`."
  [path]
  (make-path-exists-without-binding-clause path the-existence-matcher))

;; 3.
(define-record-type
  ^{:doc "A clause that matches the value of `key` of a map using `matcher`."}
  KeyMatchesWithoutBindingClause
  (make-key-matches-without-binding-clause key matcher)
  key-matches-without-binding-clause?
  [key key-matches-without-binding-clause-key
   matcher key-matches-without-binding-clause-matcher])

(define-record-type
  ^{:doc "A clause that matches the value of `key` of a map using `matcher`. When evaluated, binds it's result to `binding`."}
  KeyMatchesWithBindingClause
