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 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.

Reply via email to