5 ms·
I think the instrumenting and generator stuff gets disproportionate attention. For me by far the biggest win from spec has been with parsing. This completely ch
by gw 6y ago
I think the instrumenting and generator stuff gets disproportionate attention. For me by far the biggest win from spec has been with parsing. This completely changes how you'd write a library that takes a data structure and parses it into something meaningful (for example, what hiccup does for html or what honeysql does for sql).
In the past, this required a lot of very ugly parsing code and manual error-checking. With spec, you write specs and call s/conform. If it failed, you get a nice error, especially if you pair it with expound. If it succeeded, you get a destructured value that is really easy to pull data out of. I've done this in a half dozen different libraries and i'm pretty sure i wouldn't have even written them without spec.
- stingraycharles 6y agoand if you then combine s/conform with core.match, you can build really elegant code to traverse these structures.
- bgorman 6y agoWhy not just pattern match immediately if you are going to bother with using core.match?
- stingraycharles 6y agoHow would you pattern match with Clojure without using core.match? Do you mean using another library? Edit: oh I understand what you mean, you were thinking of skipping the s/conform part, and use core.match directly. Personally, I consider spec an excellent library to describe the shape of data, and core.match allows for better describing the actions you want to take based upon that. For example, with spec you can define a bunch of alternatives using s/or, and then use core.match to then easily traverse the results. It’s more a matter of separation of concerns to me. I don’t use core.match for validation or describing shapes of data.
- jmiskovic 6y agoDo you have to adapt spec definition to core.match somehow? Is there a resource to read more how to use them together?
- stingraycharles 6y agoNo you don't have to do anything. Let's say I have something like (s/def :thespec (s/or :foo ::foo :bar ::bar)) I can then use it in conjunction with core.match like (match [(s/conform :thespec val)] [:foo x] (do-something-with x) [:bar y] (do-something-else-with y)) Which imho is an easier way to navigate these things.
- adamkl 6y agoTotally agree with this. I started playing with spec because of the idea of automated test generation, but the reality of it is that I use it as a super-charged validation library. I think this emphasis actually does the library a disservice in that I see new users ask questions along the lines of "Should I use s/valid? to manually check inputs to my API"? The answer to that, in my usage, is "Yes! Of course!", but many people seem to think that they are using Spec wrong if they use it for something other than instrumentation and generation.
- Scarbutt 6y agoThis is why languages like Ocaml are really nice to work with for this stuff.
- didibus 6y agoDoes OCaml have a good parsing DSL build in?
- agumonkey 6y agocan you "stream" conform ? for UI live input so that "john mcallister" yields { :name "john" :lastname "mcallister" } but "john " would yield { :name "john" :lastname nil } (or :todo even)
- didibus 6y agoYou could call it on every input change, though I'd say Spec conforming is not the most performant parsing library in the world, so not sure if it be fast enough for running it on each input.
- agumonkey 6y agoyeah that's why I was looking for a lazy / stream variant in case it wasn't already possible /me goes to prolog
- didibus 6y agoYup, surprised the article doesn't mention parsing. When writing complicated macros, Spec conforming is so useful!
- marxama 6y agoI remember doing just that - writing some ugly parsing code, thinking that I should be a good team member and add some specs for what I was doing, and when I tried calling conform... Oh, it did the parsing for me!