Fork me on GitHub
#clojure-spec
<
2017-12-09
>
mbjarland11:12:51

I have a question, I’m using spec to validate the format of a “layout string” and in the spec I use conformers to convert from string to seq of chars:

(s/def ::layout-string
  (s/and string?
         not-empty
         (s/conformer seq)
         (s/+ (s/alt :col-align-bracket-expr
                     (s/cat :left-bracket #{\[}
                            :col-align-char #{\L \C \R \l \c \r}
                            :right-bracket #{\]})
                     :col-padding-non-bracket-char
                     (complement #{\[ \]})))
         (s/conformer char-seq->str-conformer)))
, is conformers the way to go or is there some cleaner way to deal with strings as sequences of chars?

mbjarland11:12:03

I was hoping to use https://github.com/bhb/expound to make the error messages more readable, but expound does not seem to support conformers

mbjarland11:12:26

I think I’m landing at using instaparse for parsing strings instead of spec. Seems like coercing proper error messages (including the location in the string etc) from spec would be more work than it’s worth for this problem

Alex Miller (Clojure team)13:12:54

While spec can be twisted into parsing strings, it’s not designed for that and it’s going to be way slower than either a proper regex or a parser.

Drew Verlee17:12:59

does anyone have an example of how you would conform a string into a data structure, like a hasmap: (conform ::foo "8/blue") => {:age 8 :eye-color "blue"} It seems i would need to specify almost like a regex over the string. This feels doable, but i'm not sure.

mpenet17:12:21

See s/conformer. You basically pass a fn to it that does the conforming or returns ::s/invalid

mpenet17:12:47

It can also take another arg to do the inverse (aka unform)

Alex Miller (Clojure team)19:12:39

I would say, don’t use spec for this, use a parser like instaparse

Alex Miller (Clojure team)19:12:27

spec is about describing the structure of Clojure data, not strings

borkdude20:12:39

I was going to ask here, Instaparse allows to hide output or hide tags to prevent extra nesting. Is such a thing with Spec also possible?

aengelberg20:12:05

You could maybe use s/and and s/conformer to flatten things as they are being parsed / conformed.

genec20:12:47

what's the correct set of dependencies for using spec?

genec20:12:49

:dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/spec.alpha "0.1.94"]

Alex Miller (Clojure team)20:12:30

It includes spec so you don’t need to declare that

Alex Miller (Clojure team)20:12:32

Use of generators is optional. If you want that, you’ll also need [org.clojure/tools.check “0.9.0”]

genec20:12:12

@alexmiller thanks. I'm going to use spec to validate csv files, seems like a good fit

Alex Miller (Clojure team)20:12:34

I don’t think that’s a good fit

Alex Miller (Clojure team)20:12:54

CSV is text with tricky quoting rules

Alex Miller (Clojure team)20:12:11

The right tool is a parser, like instaparse

Alex Miller (Clojure team)20:12:40

Spec is for Clojure data

genec20:12:01

hmm... I'll take a look at instaparse. I have fields that can either be an int or "Missing", which I need to create a log of an errors for the user to correct before importing the file, which is why I thought spec would be good for that

guy20:12:08

Could you use instaparse to parse the data, then use clojure spec to just check it after?

genec20:12:49

I suppose I could, I was just going to use one of the csv libs

guy20:12:57

Yeah i just used https://github.com/clojure/data.csv which was pretty handy

borkdude20:12:07

@aengelberg thank you — and thanks for Instaparse, it’s a really amazing tool 🙂

aengelberg21:12:02

Glad you find it useful!

borkdude22:12:27

Yes, just used it for the first time to solve a puzzle, inspired by someone who did it in PureScript using parser combinators.