Fork me on GitHub
#malli
<
2020-12-23
>
borkdude08:12:55

@ikitommi In other languages people usually define this as an ADT. Maybe :enum can also be used for this?

borkdude08:12:16

(I didn't see any docs about :enum in the README, only examples)

ikitommi08:12:59

:enum is about values, :or is about schemas:

[:or
 [:map [:type [:= :work]] [:value string?]]
 [:map [:type [:= :personal]] [:value string?]]]
fixed, thanks to @borkdude

borkdude08:12:21

right, that's what I was thinking

ikitommi08:12:33

but, :or does a linear scan over schema, :multi can be much more efficient.

borkdude08:12:41

why did you have to write [:work [:map [:type [:= :work]] [:value string?]]] with :multi but [:map [:type :work] [:value string?]] with :or?

ikitommi08:12:42

(`either` was deprecated in Plumatic Schema because of this, malli supports that as it’s usefull to describe the real world, despite being slow)

ikitommi08:12:14

could be:

[:work [:map [:type string?] [:value string?]]]

borkdude08:12:27

if you support :case for a closed world of possibilities it could possibly be even faster?

ikitommi08:12:34

… but the generator would then just generate any keyword for the :a:

ikitommi08:12:05

what kind of code would the :case emit?

borkdude08:12:08

I was referring to [:type [:= work]] vs [:type :work]

ikitommi08:12:44

oh, that’s my bug. [:type :work] doesn’t work.

ikitommi08:12:59

looks for :work from the registry, which doesn’t exist.

borkdude08:12:32

(I have no idea what :case would emit, just bouncing an idea)

ikitommi08:12:33

[:= :work] is basically same as [:enum :work]

borkdude08:12:58

so [:map [:enum :work :personal] [:value string?]] would also work

ikitommi08:12:38

[:map [:type [:enum :work :personal]] [:value string?]] yes

ikitommi08:12:07

but if the :type effects the :value , or any other parts of the schema, then :multi is the way.

borkdude08:12:18

does it generate a multi-method behind the scenes?

ikitommi08:12:35

no, it’s closed and immutable by design.

ikitommi08:12:02

just a dispatch map from key -> schema. and the key is looked up using the :dispatch function.

ikitommi08:12:28

:dispatch function is applied to value, which returns the :multi key, which selects the schema

ikitommi08:12:09

and, :dispatch can be a sci-function, of course 🙂

ikitommi08:12:25

(m/validate
  [:multi {:dispatch 'first}
   [:sized [:tuple keyword? [:map [:size int?]]]]
   [:human [:tuple keyword? [:map [:name string?] [:address [:map [:country keyword?]]]]]]]
  [:human {:name "seppo", :address {:country :sweden}}])
; true

ikitommi08:12:12

so, there is always a map-lookup, so not as fast as case, but it would require code-generation, which would mean a macro.

borkdude08:12:15

yeah, that makes sense

ikitommi08:12:30

could add a :conditional, where the entry keys are functions, and the first one will match. Like :or, but more explicit and short-circuits on first match:

[:conditional
 [map? [:map [:x int?]]]
 [int? [:int {:min 1, :max 2}]]]

ikitommi08:12:28

malli.core is distilled into tons of helper functions to build new schemas, really easy to add things like this atm.

borkdude08:12:48

doesn't :or short-circuit?

borkdude09:12:51

btw, I also implemented case as a map-lookup in sci, same problem ;)

👍 3
ikitommi09:12:05

sorry, it does. I think the issue is that you can have multiple branches that would match, making the rest effectively unreachable.

ikitommi09:12:07

also, the :or tranformation is bit hacky, depending whether you are doing decoding or encoding, we need to check if the transformation turned the value valid or not. that’s slow.

ikitommi09:12:24

… but, works 🙂