nedap/speced.def

Create `speced/promise` `speced/promise-of`

vemv opened this issue · 2 comments

vemv commented

Context

'Promise' return values are non-trivial to spec: derefing them on :post would make that defn blocking, defeating the purpose of promises

Task

Implement speced/promise (a promise replacement), plus speced/promise-of(a spec predicate)

Example:

(defn promise [spec]
  (let [p (clojure.core/promise)]
    (fn [deliverable]
      (assert (check! spec deliverable))
      (deliver p deliverable))))

(spec/valid? (speced/promise-of ::foo) (speced/promise ::foo)) ;; true

Acceptance criteria

  • Works analogously to clojure.core/promise
  • The resulting spec checking is meaningful / strong

Additional resources

https://github.com/nedap/postman-clj/pull/38

Would promise-of block/defer the promise to check the result of the promise; or check whether the value is a speced/promise is passed and the spec matches.

If the latter; how would we determine the match?

(spec/def ::foo string?)
(spec/def ::bar (spec/and ::foo (complement (clojure.string/blank?)))

(spec/valid? (speced/promise-of ::foo) (speced/promise ::bar))

this should be valid, but on spec1 i'm not sure we can determine this 🤔 (spec2 might have possibilities)

vemv commented

or check whether the value is a speced/promise is passed and the spec matches.

the latter - the point of distinguishing between promise and promise-of is being able to check specs without blocking. Else we'd just have a unified promise API

i'm not sure we can determine this

Specs are a protocol:

https://github.com/clojure/spec.alpha/blob/5a4834eeb2967b2eca382efe0afcb3f590bdb3c2/src/main/clojure/clojure/spec/alpha.clj#L44