Fork me on GitHub
#clojure-spec
<
2019-12-10
>
bortexz09:12:01

In spec2, can you create a subschema of a schema, like doing select-keys on schema keeping the optionality?

vlaaad10:12:05

isn't it what select is for?

bortexz10:12:20

select returns the required keys from a schema on a specific context, I am looking for something to generate schemas of optionals from a subset of keys of another schema

Alex Miller (Clojure team)13:12:29

Schema keys are all optional. I don’t understand what you’re trying to do.

bortexz14:12:47

Imagine I have an entity, for which I have a spec/schema with a set of keys that it can have. Now, I would like to spec the request parameters to modify the given entity. You can only modify half of the parameters of that entity, although each of them is still optional. How would I approach this case? Does it make sense?

Alex Miller (Clojure team)14:12:01

a select is exactly the case of specifying a more constrained structure based on a schema, intended specifically for "in a context", like request parameters

👍 4
Alex Miller (Clojure team)14:12:02

if the keys are optional, then the existing schema suffices

👍 4
bortexz14:12:54

I see, in terms of validation and instrumentation it makes sense, just use the “big schema” with all possible keys and select if there is any requirement. I guess what I was trying to achieve was more aligned with a “specification / documentation” use of schema, so I could tell which of the keys are supported by a specific function, rather tan required

bortexz14:12:31

Is there in spec any concept or would it make sense to have something to specify that a property is supported? with a meaning of The property will be used if it exists, but it's not required , or is it something that should be left to documentation / outside of the code specification?

Alex Miller (Clojure team)14:12:31

nothing like that in spec, no

👍 4
bortexz15:12:40

Thanks alex. Would it make sense in the context of spec? I think it could be something very close to the concept of select . As I imagine it, would be: • schema: All keys that travel together, outside of function context (all are optional, although wouldn’t optional also be contextual? optional meaning supported or used) • select: All keys that are used in a specific context (With the slight change that it would allow to select optional and required keys for the case mentioned above) Is this something that makes sense? Am I missing something in how I conceive spec?

Alex Miller (Clojure team)15:12:16

schemas are all optional, select is all about what's required

👍 4
bortexz15:12:24

I (think I) understand, what I am trying to achieve maybe fits more into the metadata space (saying what is used if specified, for auto generated doc or generative test) rather than in spec. I am trying to wrap my mind around the philosophy behind the schema/select approach, I already find it quite useful how it is now, although sometimes I find myself in a 3-concepts space rather than two (schema/select) when thinking about the information model: 1. What travels together (big schema with all related kw, e.g. domain entity) 2. What a context uses (subset of kw used by the fn. Not everything used is required, but it’s not ignored) 3. What a context requires to work properly (required set of kw for the fn to work) Maybe it makes sense to have smaller schemas in 2. with shared kw with 1. , or to have 2. just as metadata of the fn outisde spec. Any ideas on this ? Seems a good time to re-watch Maybe not , I might be missing something about the philosophy of the tool

Alex Miller (Clojure team)16:12:57

On 2, you don't have to use a predefined schema, you can just restate specifically what attrs are allowed, which may be a smaller set

Alex Miller (Clojure team)16:12:35

or you can just make a schema that is a smaller set

👍 4
bortexz16:12:49

> or you can just make a schema that is a smaller set I’ll go for that. Which brings me to the beginning, create schema from subset of another schema, (or join schema’s together). Probably something that can be done as tooling outside spec2. Looking forward for a final release 🙌 cheers!

seancorfield17:12:54

s/merge could merge smaller schemas to make a bigger schema, yes?

👍 4
bortexz17:12:24

^ Indeed !

bortexz17:12:12

By <https://github.com/clojure/spec-alpha2/wiki/Schema-and-select> I think s/union would be the one to use on schemas

bortexz17:12:10

Thinking about my previous comment of generating schema from subset of schemas, it doesn’t make any sense :man-facepalming: Schema’s syntax is just the set of keys (when ns-kw at least)

Alex Miller (Clojure team)17:12:46

We may actually re-purpose “union” for nonflowing s/and so don’t get too attached to that name :)

👍 4
seancorfield18:12:03

Usual caveat: Spec2 is a moving target whose function names may change and/or whose semantics may change, potentially several times 🙂

👍 4
bortexz18:12:55

Yeah, luckily it is a personal project with a small codebase, refactors aren’t very painful (I do lots of them to try new approaches). Having that into account, I was avoiding to go much further than def’ing schemas, which it feels already useful to define my domain entities and properties (and understand them) as a common ground between a set of external services that all of them use similar entities but each one of them with different set of properties and property names and formats

mpenet11:12:25

basically spec will happily validate against stuff that was never declared, just checking for presence of the key as if any?

mpenet11:12:31

the docstring is not really clear about that one

Alex Miller (Clojure team)13:12:47

s/keys checks that required keys exists and that all registered keys have values that conform

Alex Miller (Clojure team)13:12:07

So, not a bug. I think you’ll get exceptions if you try to gen though

mpenet14:12:12

yes, it throws

danielcompton20:12:17

Is there a way to validate a "closed select"? I can see how to check a schema with closed settings, but it doesn't seem like that works for selects?

(s/def ::a (fn [x] 
             (Thread/sleep 2000)
             true))
(s/def ::b string?)
(s/def ::b-sch (s/schema [::b]))
(s/def ::b-sel (s/select ::b-sch [::b]))

(comment
  (s/valid? ::b-sel {::b "a" ::a nil})
  ; => <waits> true
  
  (s/valid? ::b-sch {::b "a" ::a nil} {:closed #{::b-sch}})
  ; => <immediately> false

  (s/valid? ::b-sel {::b "a" ::a nil} {:closed #{::b-sch}})
  ; => <waits> true

  (s/valid? ::b-sel {::b "a" ::a nil} {:closed #{::b-sel}})
  ; => <waits> true
  )

Alex Miller (Clojure team)00:12:47

I think the select linkage is not fully implemented yet, long story, wip

👍 4
danielcompton20:12:17

The use case is for API boundaries, where you want to make a selection of keys that you will accept, fail if extra keys are provided, and especially to not validate the extra keys before failing