clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
borkdude 2020-10-31T14:02:21.149100Z

The ::invalid keyword occurs 67 times in the spec repo:

$ ./grasp ~/git/spec.alpha/src -w -e "(fn [k] (= :clojure.spec.alpha/invalid (unwrap k)))" | wc -l
      67

teodorlu 2020-10-31T14:26:46.149400Z

And you're finding both fully qualified :clojure.spec.alpha/invalid and shorthand ::invalid / ::s/invalid uses? Nice! I'm curious about use-cases for grasp in tooling for refactoring.

borkdude 2020-10-31T15:01:45.149600Z

yes

👍 1
kirill.salykin 2020-10-31T16:55:19.152500Z

Hi please advice, how I can write a spec for :fileds

(s/explain-data ::fields [{:name "aaa" :type "bbbb"} {:name 1 :type "cccc"}])
so it checks that fields/name is unique - fails on every non unique entry and the spec also contains path of the non unique row Thanks

borkdude 2020-10-31T18:59:46.153200Z

@kirill.salykin The uniqueness of the name is a property of the collection, not of one item

user=> (s/def ::unique-names (fn [xs] (= (map :name xs) (distinct (map :name xs)))))
:user/unique-names
user=> (s/explain ::unique-names [{:name :foo} {:name :bar}])
Success!
nil
user=> (s/explain ::unique-names [{:name :foo} {:name :foo}])
[{:name :foo} {:name :foo}] - failed: (fn [xs] (= (map :name xs) (distinct (map :name xs)))) spec: :user/unique-names

kirill.salykin 2020-10-31T19:00:49.154300Z

I understand and agree thought there is a dark magic to get indecies of non-unique elements, but apparently no thanks for the answer

borkdude 2020-10-31T19:01:12.154700Z

There might be, but I don't know if it's pretty

kirill.salykin 2020-10-31T19:03:47.156900Z

maybe there is a way shape spec output in a way as it reports per failed element (eg with s/problems, path (`:in []`) and predicate?)

borkdude 2020-10-31T19:10:06.157400Z

@kirill.salykin Maybe something like this:

user=> (s/def ::unique-names (s/and #(group-by :name %) (s/every-kv any? #(= 1 (count %)))))
:user/unique-names
user=> (s/explain ::unique-names [{:name :foo} {:name :foo}])
Execution error (UnsupportedOperationException) at user/fn (REPL:1).
nth not supported on this type: PersistentArrayMap
but I'm getting an exception

kirill.salykin 2020-10-31T19:11:14.157500Z

interesting… so (s/and ) behaves like ->?

2020-10-31T19:11:31.157700Z

no afaik

borkdude 2020-10-31T19:15:45.158700Z

@kirill.salykin Ah, I needed s/conformer:

user=> (s/def ::unique-names (s/and (s/conformer #(group-by :name %)) (s/every-kv any? #(= 1 (count %)))))
:user/unique-names
user=> (s/explain ::unique-names [{:name :foo} {:name :foo}])
[{:name :foo} {:name :foo}] - failed: (= 1 (count %)) in: [:foo 1] at: [1] spec: :user/unique-names

1
kirill.salykin 2020-10-31T19:16:17.159200Z

you are magician! thank you so much!

borkdude 2020-10-31T19:16:39.159300Z

It needed s/conformer around the first spec

2020-10-31T19:18:43.159600Z

til, thanks 🙂

borkdude 2020-10-31T20:23:57.160200Z

I've made binary versions of grasp available in the #grasp channel now. Clojure spec on the command line, yeah :)