Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Spec by

One of the problems that I've run into while using Spec 2.

(s/def ::number      number?)
(s/def ::boolean     boolean?)
(s/def ::schema      (s/schema [::number ::boolean]))
(s/def ::only-number (s/select ::schema [::number]))
(s/def ::this-works  (s/keys :req [::only-number]))
(s/def ::this-fails  (s/schema [::only-number]))
Execution error (AssertionError) at clojure.alpha.spec.impl/schema-impl (impl.clj:422).
Assert failed: (every? (fn* [p1__6948#] (if-let [sp (s/get-spec p1__6948#)] (not (select? sp)) true)) ks)

I made up this example to replicate an error I've got while I was creating a wrapper for AWS DynamoDB REST API.

1 Answer

+1 vote
by

No, this is not supported. s/union can be used to combine schemas.

https://github.com/clojure/spec-alpha2/wiki/Schema-and-select

by
edited by
My understanding of s/union is that you would use it to combine two specs that are at the same hierarchical level as in (s/union ::user/private ::user/public).

What I want here is a hierachical structure as in this JSON structure:
{"TransactItems": [{"Get": {"TableName": "string", "Key": "string"}}]}

(s/def ::transact-schema (s/schema [::TableName ::Item ::Key ::ConditionExpression]))
(s/def ::Get                          (s/select ::transact-schema [::TableName ::Key]))
(s/def ::ConditionCheck  (s/select ::transact-schema [::TableName ::Key ::ConditionExpression]))
(s/def ::Put                          (s/select ::transact-schema [::TableName ::Item]))

(s/def ::TransactGetItem      (s/schema [::Get]))
(s/def ::TransactWriteItem  (s/schema [::ConditionCheck ::Put]))
(s/def ::TransactItems
    (s/or :get     (s/coll-of ::TransactGetItem :kind vector?)
              :write (s/coll-of ::TransactWriteItem :kind vector?)))

Here I am specifing what the value of "Get" can be at the inner level (a map that contains "TableName" and "Key" as keys) and what the value of "TransactItems" can be at the outer level (an array of maps that contain "Get" as a key or an array of maps that contain "Put" and "ConditionCheck" as keys).

Source: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html
by
Schemas are sets of keys. Unions combine schemas (sets of keys) into one larger set of keys. They do not have nesting or imply hierarchies.

Selects specify required parts of a nested map structure (based on a schema at the top level, but also pursuant to schemas at lower levels if the top level key refers to a schema).

There is no way currently to talk about maps of colls of maps in the select selection, although that is something we are considering. I think that's the problem space you're asking about.
by
Understood, thanks.
Welcome to Clojure Q&A, where you can ask questions and receive answers from members of the Clojure community.
...