malli

https://github.com/metosin/malli :malli:
oly 2021-07-05T07:14:29.293Z

is there a way to have different map layouts, I wanted to do something like this

[:map [:coord [:or 
               [:map {:closed true}]
               [:map {:closed true} [:x int? :y int?]]]]]
{:coord {}}
{:coord {:x 1 :y 1}}
I know I can make the whole map optional but what about allowing an empty map or a map with fixed keys, I tried a few things but could not find a way.

alpox 2021-07-05T07:44:40.293600Z

@oliver.marks I think this works if you use for the second :map:

[:map {:closed true} [:x int?] [:y int?]]

oly 2021-07-05T07:47:17.295400Z

yeah that works for the second map, just not sure how to make it work also for an empty map I tried putting optional in various places and tried :or and a few other things oh I might have missed some brackets above but its more an an illustration of one of the methods I tried

oly 2021-07-05T07:48:16.296400Z

[:map {:closed true :optional true} [:x int?] [:y int?]]
also tried this but that does not work, I know I could make the :x and :y keys optional but really I want an all or nothing method

alpox 2021-07-05T07:49:26.297100Z

I tried it with your :or above and that worked (after adding the missing brackets)

alpox 2021-07-05T07:52:54.298400Z

oly 2021-07-05T07:53:00.298900Z

this passes ? {:coord {}} when I run it through m/valid i get missing keys or I was yesterday when I was testing πŸ˜›

oly 2021-07-05T07:53:52.299400Z

nice, I will re check what I have maybe there was a different error which I did not spot

oly 2021-07-05T07:56:19.299700Z

@alpox

[:map [:coord [:or 
               [:map {:closed true}]
               [:map {:closed true}
               [:x {:optional false} int?]
               [:y {:optional false} int?]]]]]

oly 2021-07-05T07:56:50.300400Z

what about that, I think because the key do not have the optional map the :or is irrelevant anyway

oly 2021-07-05T07:58:27.301900Z

although perhaps thats it, perhaps its optional thats messing me up looking at your screenshot again I can see it fails when one of the keys are missing

oly 2021-07-05T08:09:05.302900Z

@alpox thanks for your rubber ducking, not an issue with malli I had 2 schmeas with similar name and was updating the wrong one πŸ˜•

alpox 2021-07-05T08:10:28.303100Z

Oups πŸ™‚ np

Ben Sless 2021-07-05T08:29:47.304400Z

I constantly get the feeling that I'm missing a schema to talk about map schemas in terms of key-value pairs

Ben Sless 2021-07-05T08:30:37.305100Z

an annoying example to implement is mutual exclusion, such as a map which can have x, y and (z or u)

Ben Sless 2021-07-05T08:30:48.305500Z

where z and u have different value types, too

Richard Hundt 2021-07-05T09:47:04.309300Z

@ikitommi I've created https://github.com/metosin/malli/issues/472 with a test case which demonstrates the issue.

Ben Sless 2021-07-05T11:01:07.309700Z

@richard.hundt I profiled you example, it looks like CPU mostly goes towards parsing the schema. If you wrap every def-ed schema with a schema constructor it seems to be way more efficient, would you mind trying?

Richard Hundt 2021-07-05T11:02:26.310100Z

D'you mean just wrapping it in a function which returns the structure? (I'm not sure what you mean by "schema constructor")

Ben Sless 2021-07-05T11:06:25.310400Z

like so;

(def A1
  (m/schema
   [:map
    {:encode/test {:leave encode} :decode/test decode}
    [:type [:= "A1"]]
    [:value float?]
    ]))

Richard Hundt 2021-07-05T11:06:44.310600Z

thanks, I'll try

Ben Sless 2021-07-05T11:06:44.310700Z

m/schema parses the children once

Ben Sless 2021-07-05T11:06:57.311Z

your implementation has no way to cache these results

Ben Sless 2021-07-05T11:07:31.311200Z

It's a bother to do from scratch, you can take this

Ben Sless 2021-07-05T11:07:56.311600Z

Ben Sless 2021-07-05T11:08:06.312Z

thanks slack, very helpful

Richard Hundt 2021-07-05T11:08:38.312200Z

thank you

Ben Sless 2021-07-05T11:09:02.312600Z

there, more convenient

Richard Hundt 2021-07-05T11:09:38.312800Z

yeah, that's pretty much instant now, I'll try it on our production code

Ben Sless 2021-07-05T11:19:52.313Z

πŸ‘

Richard Hundt 2021-07-05T11:36:05.313200Z

Perfect. Thanks Ben! What shall I do with the github issue? Do I close it, or are you planning on making changes to parsing?

ikitommi 2021-07-05T12:34:03.314900Z

Hear hear. I think something like malli-keys-relations should be there. With qualified keywords, it’s less boilerplate (but, still has):

[:or 
 [:map ::x ::y ::z]
 [:map ::x ::y ::u]]

ikitommi 2021-07-05T12:34:51.315500Z

spec-style would be:

[:map ::x ::y [:keys/or ::y ::u]]

ikitommi 2021-07-05T12:36:06.316400Z

maybe:

[:and
 [:map ::x ::y ::z ::u]
 [:keys/or ::z ::u]]

ikitommi 2021-07-05T12:39:55.316800Z

… and the mandatory JSON Schema way for this: https://json-schema.org/understanding-json-schema/reference/conditionals.html

ikitommi 2021-07-05T12:43:28.316900Z

I closed the issue, no plans on making the parser faster or caching at the moment. Thanks for @ben.sless for digging into this πŸ™‡

Ben Sless 2021-07-05T12:46:06.317600Z

I think it is worth to leave a comment on the issue and perhaps a note in the readme regarding references to uncompiled schemas

Ben Sless 2021-07-05T12:46:50.317800Z

And you're welcome πŸ™‚ Turns out I was completely wrong regarding the transformers and satisfies?

Ben Sless 2021-07-05T12:47:57.318Z

I see you left a comment with a link to the gist, so that would leave only the readme

Ben Sless 2021-07-05T12:49:33.318600Z

JSON Schema's BNF was one of the motivations for it

Ben Sless 2021-07-05T12:50:15.319500Z

> map which contains at least one ::x where ::x is [:or [:x int?] [:y float?]]

Ben Sless 2021-07-05T12:57:18.320600Z

If we had it we could define JSON Schema with malli (translating the ebnf is straightforward), then define encoders and decoders to transform between the two

ikitommi 2021-07-05T13:14:13.320700Z

if you have idea what and where to write this, please do πŸ™‚

1πŸ‘
ikitommi 2021-07-05T16:28:41.324100Z

added a video of the new function instrumention. three apis: advanced, normal users and for the lazy: https://github.com/metosin/malli/pull/471

4πŸŽ‰
ikitommi 2021-07-05T16:28:52.324400Z

comments welcome