In Clojure’s Malli library, how can I define a schema for a list that contains • at least one string, • exactly one integer, and • any number of doubles, while not allowing any other types — and where the elements can appear in any order (they can be interleaved)? Is it possible to express this without using :fn? 🧪 What I tried: I explored using Malli’s sequence regex combinators like :catn, :alt, and :, but they seem to assume a *fixed order. For example, something like this:
[:catn
[:strings [:+ string?]]
[:i int?]
[:doubles [:* double?]]]
works only when elements appear in that specific order (strings first, then int, then doubles).
However, I need a schema that allows any interleaving order (e.g. [“a” 1 2.0 “b” 3.0] should also be valid).
Is there a declarative way to express this — or do I need to rely on a :fn predicate?I've never used xsd, what would the equivalent look like in that @kayulai2?
malli’s primitives are quite close to the primitives of regular expressions. I encourage you to try and write a regular expression that matches this type and see how tricky it is for yourself
yes, very tricky indeed. but it is a very common type of validation in xml validation.
for this particular case it's not too difficult to work out by hand since the schemas are 'disjoint', if you think of them as regexes #"s+", #"i", #"d*" you can express each as a finite state machines with 2,2,1 states respectively, and draw their composition as an FSM with 4 states. The problem is with projecting it back down into a regex form where in general you'd get an exponential explosion of the state space - in this case you get something like #"d*(id*s|s[ds]*i)[ds]*" (might be further reducible)
right. and I think a regex like that, or the equivalent expressed as a Malli schema, is actually much harder to read than a function
yeah,I suspect if you were determined enough you could 'package' it up into a schema-generating util or custom schema like [:interleaved-seqs [:+ :string] [:cat :int] [:* :double]] for readability, but would have to be careful not to run into those pathological state space explosions, at some point regular languages might just be the wrong tool for the job
thanks for the ideas. I encounter this problem when I trying to use malli to validate an xml. It is quite easy to express in xsd, but turn out hard to mimics in malli.
this works if you allow :fn schemas (ah, just noticed your last sentence)