Hi Leon, I think you're looking for fspec <https://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec/fspec>, unless I'm misunderstanding something. I wrote up an example <https://gist.github.com/atroche/731f80376985773c60d5e943b38d8052> that might be helpful.
@Ryan thanks for starting this thread, and @Alex thanks for responding. It's been an interesting discussion! Cheers, On Monday, 13 June 2016 07:17:56 UTC+10, Leon Grapenthin wrote: > > Alex, thank you for the long and detailed response. > > The direct linking issue and Ryans last example make me wonder whether the > hard rule > > "If A and B are both instrumented and if A ever calls B violating B's > spec, A's spec is broken" > > holds? If so the direct-linking issue would probably be a non-concern > since instrumentation within the standard library would not matter because > one could assume that the core lib has been tested already against it's own > specs. If the latter is true (I'm not quite sure) it would appear > worthwhile to look for a counter-example against the former in the standard > library. > > I'd highly appreciate if you could give an example for checking the arity > of a passed in function since I don't see how to do that right now except > for maybe using reflection? > > On Sunday, June 12, 2016 at 5:45:17 PM UTC+2, Alex Miller wrote: >> >> >> 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 [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
