Author here. Happy to answer any questions or comments.
Hey, I like what you're doing here, I think I'll use this... it gives you a lot of the benefits of a deep type system while being completely orthogonal to the design of the program and without the cognitive overhead of a complex type system. Also, functional programming is heavily focused on data transformations, which in practice means lots of deeply nested heterogenous data structures... these types of structure ar…
Schema for Clojure(Script) Data Shape Declaration and Validation
11–20 of 58 posts
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#12Author here. Happy to answer any questions or comments.
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#13Author here. Happy to answer any questions or comments.
What I'd like to see is something similar to what we did — checking more than just types. Here's an example from our code:
(conforms example-object [map :from string? :to [map :required-keys {"products" [seq string?] "type" [seq #{"type1" "type2"}]}]])
This describes a map containing mappings from strings to maps of a certain kind (where "products" and "type" are required, "products" must map to a sequence of strings and "type" must map to a sequence of strings from a specific set).
From our "conforms" docstring:
Returns true if value conforms to typespec. typespec can be either: - a string, which value must match literally; - a predicate, which value must satisfy; - [seq sub-typespec], which means that value must be a collection of elements, each of which must conform to sub-typespec; - [map specifiers...], where optional specifiers may include: :from sub-typespec -- keys in the map must match sub-typespec; :to sub-typespec -- likewise for values; :required-keys [key1 typespec1 key2 typespec2...] -- map must include the required keys and their values must match the typespecs.
We don't use that for function contracts and it might be overkill for that, but I'm pretty certain I'd like to be able to specify more than just types for map keys. A list of possible values would be tremendously useful.
This could provide you with some ideas. I can of course contribute the "conforms" function (although it isn't that difficult to write).
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#14Interesting work. BTW, there's a typo: "shee here" should be "see here".
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#15Author here. Happy to answer any questions or comments.
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#16Author here. Happy to answer any questions or comments.
This is a very good idea. And the reason I say that is because in our code base we have developed something similar, feeling the need for it :-). Our stuff is half-baked, though and I never got around to releasing it. What I'd like to see is something similar to what we did — checking more than just types. Here's an example from our code: (conforms example-object [map :from string? :to [map :required-keys {"products"…
Actually, schema can express arbitrary constraints. Your example translates to schema as:
{String {(s/required-key "product") [String]
(s/required-key "type") (s/enum "type1" "type2")
s/Any s/Any}} ;; allow any other k-v pairsRe: Schema for Clojure(Script) Data Shape Declaration and Validation
#17Author here. Happy to answer any questions or comments.
This is a very good idea. And the reason I say that is because in our code base we have developed something similar, feeling the need for it :-). Our stuff is half-baked, though and I never got around to releasing it. What I'd like to see is something similar to what we did — checking more than just types. Here's an example from our code: (conforms example-object [map :from string? :to [map :required-keys {"products"…
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#18Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#19A lot of my time in Clojure is spent re-reading and repl-evaluating my function implementations just to remind myself what its symbols look like. Even code I wrote an hour ago. Often I stoop to the level of caching my findings in a docstring/comment.
(defn alpha-map-sum-combining-thing
"TODO: Think of better name.
Example input: {:a 1 :b 2}
Example output: {[:a :b] 3}"
[alpha-map]
...)
Sometimes I can spot abstractions and patterns and protocols that unify a namespace of functions so that their inputs/outputs are obvious, but often I can't.This kind of tool is essential for me.
Re: Schema for Clojure(Script) Data Shape Declaration and Validation
#20Newbie here, mostly familiar with OOP. What is the difference between how Clojure and other functional programming languages declare types.
Dynamic means that their usefulness is tied somewhat to your ability to exercise code paths. Compare this to Hs's static types where the type logic of your entire program (and all dependent libraries) is checked upfront before compilation. Schemata likely must be triggered by a validation function being called on live code. Endless further argumentation about this distinction goes here.
First-class comes from Schema's dynamic nature as well but is worth further investigation. Schema look like they can be arbitrary functions of the arguments, much like inserting `assert`s at the beginning of a function and then flipping those on or off at a later time. They can also be composed/decomposed/analyzed as Clojure values. This vastly increases the flexibility and complexity of Schema for better and worse. You can express much more sophisticated invariants in your Schema than you can in Haskell types. It looks like it's even possible for these invariants to be value-based—a concept which, in static typing land, is deep into research territory.
I'd say these contract-like invariant checkers are in a pretty different boat from static types. They check different classes of things at different times and make vastly different promises. What they both provide however, so long as your Schema don't get too complex, is some wonderful "living" documentation.