Search code examples
clojureclojure.spec

Can one make a Clojure spec private?


I have a spec for a "vertex" (a 2D point in the plane, represented with a map holding two double values) and a "rectangle" (an axis-aligned rectangular area in the plane, represented by a map of two "vertex" values), defined as follows:

; vertex coordinates are doubles (need to make sure "=" doesn't try to
; compare floats in one vertex and doubles in another one, which fails)

(s/def ::vtx-x double?)
(s/def ::vtx-y double?)

; vertex is a map representing a 2D point

(s/def ::vertex (s/keys :req [::vtx-x ::vtx-y]))

; rectangle corners "low" (low x,y) and "high" (high x,y) are vertexes

(s/def ::rec-lo ::vertex)
(s/def ::rec-hi ::vertex)

; rectangle has internal sorting constraint, specified via a predicate

(s/def ::rectangle-internally-sorted
   (fn [rect]
      (let [lo-vtx (::rec-lo rect)
            hi-vtx (::rec-hi rect)
            lo-x   (::vtx-x lo-vtx)
            lo-y   (::vtx-y lo-vtx)
            hi-x   (::vtx-x hi-vtx)
            hi-y   (::vtx-y hi-vtx)]
          (< lo-x hi-x) (< lo-y hi-y))))

; rectangle is a map of two vertexes 
; representing an axis-aligned rectangular area

(s/def ::rectangle
   (s/and
      (s/keys :req [::rec-lo ::rec-hi])
      ::rectangle-internally-sorted))

Client code should be able to use specs ::vertex and ::rectangle only.

Can I hide (make private) the supporting specs?


Solution

  • You can’t and you shouldn’t. Hiding the underlying specs would only hamper users of your specs as they would not be able to make sense of spec or gen failures, or of the form returned by s/form. In that sense component specs are not an implementation detail, they inevitably surface to consumers in one way or another.

    Specs are namespaced, though. You could certainly move internals to a different namespace, which you could declare out of bounds for consumers. I would ask what is to be gained from this; information hiding has never been stressed much in Clojure, and with spec in particular (a data description language), the public/private distinction seems to me somewhat out of place.