On Sunday, June 12, 2016 at 9:22:24 AM UTC-5, Leon Grapenthin wrote: > > That looks great already. I'm also interested in what the official > workflow for adding specs to core is going to be and whether contributions > are desired. >
Still much to be determined about this but I expect that specs for core will be provided and maintained by us, because while there are a lot of obvious specs in core, there are also a lot of far more subtle ones. Some of the predicates added in the latest alpha5 (seqable?, and the simple/qualified ident/keyword/symbol) will not coincidentally be useful in these. There are also a lot of cases where there is a judgement call on how precise to be (any likely tradeoffs with testing, performance, conciseness). Also, there is a significant difference between specs for macros and functions in core. Macro args specs will always be checked during macroexpansion and this is a path toward better error messages for things like defn, ns, etc. I think it would make a lot of sense to deliver those with core. Specs for the functions in core are things you likely want instrumented at dev time, not at prod time, and fights a bit with direct linking. So, one option would be a dev build of Clojure, without direct linking and with automatic instrumentation of the functions in core. Another would be providing the core function specs externally or optionally alongside Clojure. We've only begun discussing how this will wind up. I don't agree with the map spec provided because I expect the args and ret to be seqable?, not sequential?. For example, you can map over sets, which are seqable but not sequential. This kind of subtlety is why I expect we will provide the specs for core. Once they exist, we'll be interested in tickets on them of course. There are also interesting :fn specs you can write on map - you could check that if the count of the coll args is 0 that the return is ifn? (a transducer) and that if there is at least one coll then the ret is a coll. If the colls are all finite, the return coll will have count equal to the minimum of the count of the arg colls. I think the transducer/coll difference is definitely worth spec'ing and would trigger errors in cases where some forgets the coll and accidentally gets a transducer. Is the cardinality check worth it? Probably not. identity could have a :fn spec that checks that the input and output are identical. That's really the only thing you care about (other than the cardinality of the input). Is this spec really helping you though? Not every spec pays for it's weight and this may be one that isn't worth doing. > The last example seems like it could be better because the user has to > infer how identity was called within map. > > So what we'd want is a codependent spec where we can say if you give N > sequences you have to give a fnN. Is this possible with the current ops? > Yes, with fspec - you could have a :fn spec on map that checked that the arity of the fn passed to map matched the number of colls you were passed. That would be better here than the identity spec. > > > On Sunday, June 12, 2016 at 3:52:33 PM UTC+2, Ryan Fowler wrote: >> >> Is there an effort to write specs for Clojure's core namespaces? Apologies >> if this has already been addressed. >> >> I've been tinkering with trivial (and probably wrong) fdefs on >> clojure.core/map and clojure.core/identity. It seems that the spec >> exception messages are way better than what we have now. >> >> Code is here: >> https://gist.github.com/ryfow/69a64e966d48258dfa9dcb5aa74005eb >> <https://www.google.com/url?q=https%3A%2F%2Fgist.github.com%2Fryfow%2F69a64e966d48258dfa9dcb5aa74005eb&sa=D&sntz=1&usg=AFQjCNF-D1x8PJNLKRUrdziNcKrzqh87LQ> >> >> >> ========================================================= >> Before instrumenting clojure.core/map >> ========================================================= >> Form: (into [] (map nil [1 2 3] [1 2 3])) >> Exception Class: java.lang.NullPointerException >> Message: nil >> >> Form: (into [] (map 1 [1 2 3] [1 2 3])) >> Exception Class: java.lang.ClassCastException >> Message: java.lang.Long cannot be cast to clojure.lang.IFn >> >> Form: (into [] (map identity 4)) >> Exception Class: java.lang.IllegalArgumentException >> Message: Don't know how to create ISeq from: java.lang.Long >> >> ========================================================= >> After instrumenting clojure.core/map >> ========================================================= >> Form: (into [] (map nil [1 2 3] [1 2 3])) >> Exception Class: clojure.lang.ExceptionInfo >> Message: Call to #'clojure.core/map did not conform to spec: >> In: [0] val: nil fails at: [:args :fn] predicate: ifn? >> :clojure.spec/args (nil [1 2 3] [1 2 3]) >> >> >> Form: (into [] (map 1 [1 2 3] [1 2 3])) >> Exception Class: clojure.lang.ExceptionInfo >> Message: Call to #'clojure.core/map did not conform to spec: >> In: [0] val: 1 fails at: [:args :fn] predicate: ifn? >> :clojure.spec/args (1 [1 2 3] [1 2 3]) >> >> >> Form: (into [] (map identity 4)) >> Exception Class: clojure.lang.ExceptionInfo >> Message: Call to #'clojure.core/map did not conform to spec: >> In: [1] val: 4 fails at: [:args :seq] predicate: sequential? >> :clojure.spec/args (#object[clojure.core$identity 0x15a04efb >> "clojure.core$identity@15a04efb"] 4) >> >> >> ========================================================= >> Before instrumenting clojure.core/identity >> ========================================================= >> Form: (into [] (map identity [1 2 3] [1 2 3])) >> Exception Class: clojure.lang.ArityException >> Message: Wrong number of args (2) passed to: core/identity >> >> ========================================================= >> After instrumenting clojure.core/identity >> ========================================================= >> Form: (into [] (map identity [1 2 3] [4 5 6])) >> Exception Class: clojure.lang.ExceptionInfo >> Message: Call to #'clojure.core/identity did not conform to spec: >> In: [1] val: (4) fails at: [:args] predicate: (cat :one-argument >> identity), Extra input >> :clojure.spec/args (1 4) >> >> >> -- 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.