@@ -19,7 +19,8 @@ Data-driven Schemas for Clojure/Script and [babashka](#babashka).
19
19
- [ Generating values] ( #value-generation ) from Schemas
20
20
- [ Inferring Schemas] ( #inferring-schemas ) from sample values and [ Destructuring] ( #destructuring ) .
21
21
- Tools for [ Programming with Schemas] ( #programming-with-schemas )
22
- - [ Parsing] ( #parsing-values ) , [ Unparsing] ( #unparsing-values ) and [ Sequence Schemas] ( #sequence-schemas )
22
+ - [ Parsing] ( #parsing-values ) and [ Unparsing] ( #unparsing-values ) values
23
+ - [ Sequence] ( #sequence-schemas ) , [ Vector] ( #vector-schemas ) , and [ Set] ( #set-schemas ) Schemas
23
24
- [ Persisting schemas] ( #persisting-schemas ) , even [ function schemas] ( #serializable-functions )
24
25
- Immutable, Mutable, Dynamic, Lazy and Local [ Schema Registries] ( #schema-registry )
25
26
- [ Schema Transformations] ( #schema-Transformation ) to [ JSON Schema] ( #json-schema ) , [ Swagger2] ( #swagger2 ) , and [ descriptions in english] ( #description )
@@ -379,26 +380,19 @@ default branching can be arbitrarily nested:
379
380
380
381
## Sequence schemas
381
382
382
- You can use `:sequential` for any homogeneous Clojure sequence, `:vector` for vectors and `:set` for sets .
383
+ You can use `:sequential` to describe homogeneous sequential Clojure collections .
383
384
384
385
```clojure
385
386
(m/validate [:sequential any?] (list " this" 'is :number 42 ))
386
387
; ; => true
387
388
388
- (m/validate [:vector int?] [1 2 3 ])
389
+ (m/validate [:sequential int?] [42 105 ])
389
390
; ; => true
390
391
391
- (m/validate [:vector int?] ( list 1 2 3 ) )
392
+ (m/validate [:sequential int?] #{ 42 105 } )
392
393
; ; => false
393
394
```
394
395
395
- A `:tuple` describes a fixed length Clojure vector of heterogeneous elements:
396
-
397
- ```clojure
398
- (m/validate [:tuple keyword? string? number?] [:bing " bang" 42 ])
399
- ; ; => true
400
- ```
401
-
402
396
Malli also supports sequence regexes like [Seqexp](https://github.com/cgrand/seqexp ) and Spec.
403
397
The supported operators are `:cat` & `:catn` for concatenation / sequencing
404
398
@@ -500,6 +494,54 @@ it is always better to use less general tools whenever possible:
500
494
(cc/quick-bench (valid? (range 10 )))) ; Execution time mean : 0.12µs
501
495
```
502
496
497
+ ## Vector schemas
498
+
499
+ You can use `:vector` to describe homogeneous Clojure vectors.
500
+
501
+ ```clojure
502
+ (m/validate [:vector int?] [1 2 3 ])
503
+ ; ; => true
504
+
505
+ (m/validate [:vector int?] (list 1 2 3 ))
506
+ ; ; => false
507
+ ```
508
+
509
+ A `:tuple` schema describes a fixed length Clojure vector of heterogeneous elements:
510
+
511
+ ```clojure
512
+ (m/validate [:tuple keyword? string? number?] [:bing " bang" 42 ])
513
+ ; ; => true
514
+ ```
515
+
516
+ To create a vector schema based on a seqex, use `:and`.
517
+
518
+ ```clojure
519
+ ; ; non-empty vector starting with a keyword
520
+ (m/validate [:and [:cat :keyword [:* :any ]]
521
+ vector?]
522
+ [:a 1 ])
523
+ ; => true
524
+
525
+ (m/validate [:and [:cat :keyword [:* :any ]]
526
+ vector?]
527
+ (:a 1 ))
528
+ ; => false
529
+ ```
530
+
531
+ Note: To generate values from a vector seqex, see [:and generation](#and-generation ).
532
+
533
+ ## Set schemas
534
+
535
+ You can use `:set` to describe homogeneous Clojure sets.
536
+
537
+ ```clojure
538
+ (m/validate [:set int?] #{42 105 })
539
+ ; ; => true
540
+
541
+ (m/validate [:set int?] #{:a :b })
542
+ ; ; => false
543
+ ```
544
+
503
545
## String schemas
504
546
505
547
Using a predicate:
@@ -1873,6 +1915,42 @@ Integration with test.check:
1873
1915
; => (2 1 2 2 2 2 8 1 55 83)
1874
1916
```
1875
1917
1918
+ ### :and generation
1919
+
1920
+ Generators for `:and` schemas work by generating values from the first child, and then filtering
1921
+ out any values that do not pass the overall `:and` schema.
1922
+
1923
+ For the most reliable results, place the schema that is most likely to generate valid
1924
+ values for the entire schema as the first child of an `:and` schema.
1925
+
1926
+ ```clojure
1927
+ ; ; BAD: :string is unlikely to generate values satisfying the schema
1928
+ (mg/generate [:and :string [:enum " a" " b" " c" ]] {:seed 42 })
1929
+ ; Execution error
1930
+ ; Couldn't satisfy such-that predicate after 100 tries.
1931
+
1932
+ ; ; GOOD: every value generated by the `:enum` is a string
1933
+ (mg/generate [:and [:enum " a" " b" " c" ] :string ] {:seed 42 })
1934
+ ; => "a"
1935
+ ```
1936
+
1937
+ You might need to customize the generator for the first `:and` child to improve
1938
+ the chances of it generating valid values.
1939
+
1940
+ For example, a schema for non-empty heterogeneous vectors can validate values
1941
+ by combining `:cat` and `vector?`, but since `:cat` generates sequences
1942
+ we need to use `:gen/fmap` to make it generate vectors:
1943
+
1944
+ ```clojure
1945
+ ; ; generate a non-empty vector starting with a keyword
1946
+ (mg/generate [:and [:cat {:gen/fmap vec}
1947
+ :keyword [:* :any ]]
1948
+ vector?]
1949
+ {:size 1
1950
+ :seed 2 })
1951
+ ; => [:.+ [1]]
1952
+ ```
1953
+
1876
1954
## Inferring schemas
1877
1955
1878
1956
Inspired by [F# Type providers](https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/type-providers/ ):
0 commit comments