Fork me on GitHub
#clojure-spec
<
2019-06-05
>
seancorfield00:06:48

@hlolli Remember that macros take code as input and produce code as output -- they don't see the runtime type of that code.

hlolli00:06:17

hmm, my macros are the few things in my app that I actually want to spec, because of their interface nature to my app. Yeh, I can ofc spec a presence/absence of an argument. Or spec a function that the macro calls... also a solution.

Alex Miller (Clojure team)01:06:57

the latter is a good idea

Alex Miller (Clojure team)01:06:35

keep in mind that macro specs are checked at compile time. so they can only check things you know at compile time.

Alex Miller (Clojure team)01:06:00

they can't check things about the values, because the values don't exist yet

Alex Miller (Clojure team)01:06:51

so macro specs are great for checking syntax (in core we use them for ns, defn, destructuring, etc) - things that are macros with their own syntax defined by the macro

Alex Miller (Clojure team)01:06:33

function specs are checked (when instrumented) at runtime when you have values in hand

hlolli01:06:35

yup, so this makes total sense to me. I should keep it a habit to do as little work as possible in a macro, I only need the def on a symbol, and I can forward the rest to a function*

Alex Miller (Clojure team)01:06:09

in general, having pairs like that is one common thing people do

👍 4
Alex Miller (Clojure team)01:06:48

with the caveat that the macro expands to a function call, so if you want that to be part of your public api, available outside the ns, then the function needs to be public too

Alex Miller (Clojure team)01:06:01

sometimes that feels dirty

Alex Miller (Clojure team)01:06:42

spec itself has this all over (s/and is a macro that expands to s/and-spec-impl etc)

Alex Miller (Clojure team)01:06:07

we have significantly changed that in spec 2... but that's a longer story

hlolli01:06:48

yeh I see, it's dirty in a forgiveable way. Other plus is that when I'm working in the repl, I only need to change the function once (given that I have a `(def ~symbol function) pattern), instead of re-evaling all def instances

dangercoder16:06:58

Hi! Never looked at how Spec works when it comes to data that depend on other data. Is it possible to use clojure.spec to validate and generate relational data? Let's say I have a map like this:

{:min-amount 100.00M
 :max-amount 10000000.00M
 :amount 133.00M}
:amount must be within the bounds of min-amount and max-amount.

Alex Miller (Clojure team)16:06:27

you can do this with custom generators

Alex Miller (Clojure team)17:06:23

gen the min and the max and then use gen/bind to create a generator that produces values in the range and packages them all together

👍 8
dangercoder17:06:08

Yeah I am listening to a podcast about Specmonstah right now

kszabo17:06:10

not for the usecase you mentioned, but for relational data generation

dangercoder17:06:38

Thanks @alexmiller I will look more into how custom generators work! 🙂

plins22:06:15

hey everyone, I want to spec a map with 2 values (`:key1` :key2), they are both ints so ill use integer?.. but the second key must be bigger than the first, whats the best way to achieve that?

seancorfield23:06:04

@plins wrap the s/keys in s/and and add a predicate

👍 4
seancorfield23:06:22

@plins if you need more concrete guidance than that, LMK and I'll paste an example

plins00:06:01

thank you very much but I've managed to do it 🙂