I've been using the macro below to make "types" in the context of clara-rules, where "type" has a specific semantic. If you're going to do something like this, you definitely should have a very well-defined notion of what "type" means.
(defmacro def-derive "Macros to wrap useful pattern of defining a spec and calling derive on the spec and a \"parent\" spec to create a hierarchy." ([child-name parent-name] `(def-derive ~child-name ~parent-name ~parent-name)) ([child-name parent-name spec] `(do (#?(:clj clojure.spec.alpha/def :cljs cljs.spec.alpha/def) ~child-name (#?(:clj clojure.spec.alpha/merge :cljs cljs.spec.alpha/merge) ~parent-name ~spec)) (derive ~child-name ~parent-name)))) On Wednesday, February 21, 2018 at 5:34:00 PM UTC-8, Didier wrote: > > I would actually love it if Spec was extended to have the concept of types. > > Something where every spec could be tied to a Type, and types could be > constructed to have Hierarchies. > > Not sure what the syntax would be like, but say: > > (s/def :String ::name string?) > (s/def :String ::address (s/and string? (complement string/blank?))) > (s/def :Person ::person (s/keys :req [::name ::address])) > (s/def :Homeless ::homeless (s/keys :req [::name])) > > (s/defisa :Homeless :Person) > > Types would still be predicates, and all spec would be a Type too. Types > would be optional though. A Type is the OR of all the specs predicates > defined as that Type and its children types. So in the above, :Homeless is > (s/or ::person ::homeless). > > Now, this idea might need to be refined, but the goal would be so that > Spec could be used as a modeling languages for other languages. So I could > from a Spec auto-generate a Java class model, or a Ruby model, etc. Since > now I can relate predicates to types myself. It could also allow for better > static analysis. > > Also, might make spec extra complicated and confused to mix both > predicates and types, but that could depend how its done and managed. > > On Tuesday, 20 February 2018 02:41:38 UTC-8, Jan Rychter wrote: >> >> I've been using spec for a while now, in a reasonably large code base >> (>30k lines of Clojure and ClojureScript) and there is an issue that bit me >> several times. >> >> I use conformers for coercing data that is *almost* what I need, usually >> when reading from JSON (RethinkDB). Common conformers are keyword and set. >> And it works really well, except for one problem: there is no way to know >> if data has been conformed or not. >> >> Calling s/valid? will tell me if the data is valid *if it has been >> conformed*. But what if it hasn't? Can I use the data? Is it "valid" >> according to the spec I wrote? >> >> This is a very real problem: I've spent considerable time chasing bugs >> where there was a code path which did not call s/conform. The data passed >> all validations done with valid? and the bug manifested itself far down the >> road, where something expected a keyword instead of a string, or a set >> instead of a vector. >> >> Here is a specific minimal example demonstrating what I'm talking about: >> >> (ns spectest >> (:require [clojure.spec.alpha :as s])) >> >> (s/def ::test-spec (s/and (s/conformer keyword) keyword?)) >> >> (s/conform ::test-spec "a") ;; :a >> (s/valid? ::test-spec "a") ;; true >> >> I expected the last valid? to return false, because my code does not >> expect a string, it expects a keyword, according to the spec. >> >> I might be missing something, but I would much rather see valid? tell me >> if the data is valid for use (as supplied) and have a separate >> valid-when-conformed? which tells me if the data is, well, valid when >> conformed. It seems to me that the current valid? that does two things is >> confusing and not very useful for contracts. >> >> At the very least I'd really like to see a function that tells me if the >> data is valid *as supplied*, as this is the function that I'd want to use >> when enforcing contracts everywhere in my code. >> >> Alternatively, I could stop using conformers altogether, and write >> explicit data conversion functions. That might not be a bad idea, but it >> seems other people started using conformers, too, so eventually I'll hit >> the same problem again. >> >> --J. >> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.