-
Notifications
You must be signed in to change notification settings - Fork 9
/
implies-examples
54 lines (39 loc) · 1.91 KB
/
implies-examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Perhaps the most common use of `implies` is to say \"if one key
exists in a map, another must also exist\". Because of that,
there's a special shorthand:
user=> (type! :X (pred/implies :a :b))
user=> (built-like :X {:a 1, :b 2})
=> {:a 1, :b 2}
user=> (built-like :X {:a 1})
:b must exist and be non-nil
=> nil
Note that the `then-part` is irrelevant if `:a` is not present:
user=> (built-like :X {})
=> {}
The previous example allows a single keyword to stand in for a `requires`
condensed type description like `(requires :a)`. For more complex cases,
you need a proper condensed description. In the following, if `:a`'s value is
missing or nil, keys `:b`, `:c`, and `:d` are required:
(type! :X (pred/implies (comp nil :a) (requires :b :c :d)))
Note that the `if-part` is treated the same was as elsewhere:
There can be more than one if/then pair. The following describes what
must be true of a negative value (it must also be even). But it also
allows for a string (which must be empty):
(type! :Sep {:a (pred/implies neg? even?
string? empty?)})
user=> (built-like :Sep {:a 1}) ; Neither `neg?` nor `string?`
=> {:a 1}
user=> (built-like :Sep {:a -1})
:a should be `even?`; it is `-1`
=> nil
user=> (built-like :Sep {:a \"long\"}) ; String check fails
:a should be `empty?`; it is `\"long\"`
=> nil
For cases where you want more than one condensed type description in the
`then-part`, use `all-of`:
type! :X (pred/implies integer? (pred/all-of pos? odd? prime?))
Note that, unlike most predicates in this namespace,
`implies` cannot be used as an ordinary predicate. It
doesn't return a truthy/falsey value but rather a function that
returns a function.
;