github.com/m4gshm/gollections@v0.0.13-0.20240331203319-a34a86e58a24/break/predicate/api.go (about) 1 // Package predicate provides breakable predicate builders 2 package predicate 3 4 // Predicate tests value (converts to true or false) or aborts by an error. 5 type Predicate[T any] func(T) (bool, error) 6 7 // Or makes disjunction 8 func (p Predicate[T]) Or(or Predicate[T]) Predicate[T] { return Or(p, or) } 9 10 // And makes conjunction 11 func (p Predicate[T]) And(and Predicate[T]) Predicate[T] { return And(p, and) } 12 13 // Xor makes exclusive OR 14 func (p Predicate[T]) Xor(xor Predicate[T]) Predicate[T] { return Xor(p, xor) } 15 16 // Of breakable Predicate constructor 17 func Of[T comparable](predicate func(T) bool) Predicate[T] { 18 return func(c T) (bool, error) { return predicate(c), nil } 19 } 20 21 // Wrap converts the specified predicate to the erroreable one 22 func Wrap[T any](predicate func(T) bool) Predicate[T] { 23 return func(t T) (bool, error) { return predicate(t), nil } 24 } 25 26 // Eq creates a predicate to test for equality 27 func Eq[T comparable](v T) Predicate[T] { 28 return func(c T) (bool, error) { return v == c, nil } 29 } 30 31 // Not inverts a predicate 32 func Not[T any](p Predicate[T]) Predicate[T] { 33 return func(v T) (bool, error) { 34 ok, err := p(v) 35 return !ok, err 36 } 37 } 38 39 // And makes a conjunction of two predicates 40 func And[T any](p1, p2 Predicate[T]) Predicate[T] { 41 return func(v T) (bool, error) { 42 if ok, err := p1(v); err != nil || !ok { 43 return false, err 44 } 45 return p2(v) 46 } 47 } 48 49 // Or makes a disjunction of two predicates 50 func Or[T any](p1, p2 Predicate[T]) Predicate[T] { 51 return func(v T) (bool, error) { 52 if ok, err := p1(v); err != nil || ok { 53 return ok, err 54 } 55 return p2(v) 56 } 57 } 58 59 // Xor makes an exclusive OR of two predicates 60 func Xor[T any](p1, p2 Predicate[T]) Predicate[T] { 61 return func(v T) (bool, error) { 62 if ok, err := p1(v); err != nil { 63 return ok, err 64 } else if ok2, err := p2(v); err != nil { 65 return ok2, err 66 } else { 67 return ok != ok2, nil 68 } 69 } 70 } 71 72 // Union applies And to predicates 73 func Union[T any](predicates ...Predicate[T]) Predicate[T] { 74 l := len(predicates) 75 if l == 0 { 76 return func(_ T) (bool, error) { return false, nil } 77 } else if l == 1 { 78 return predicates[0] 79 } else if l == 2 { 80 return And(predicates[0], predicates[1]) 81 } 82 return func(v T) (bool, error) { 83 for i := 0; i < len(predicates); i++ { 84 if ok, err := predicates[i](v); err != nil { 85 return ok, err 86 } else if !ok { 87 return false, nil 88 } 89 } 90 return true, nil 91 } 92 } 93 94 // Always returns v every time. 95 func Always[T any](v bool) Predicate[T] { 96 return func(_ T) (bool, error) { return v, nil } 97 } 98 99 // Never returns the negative of v every time 100 func Never[T any](v bool) Predicate[T] { 101 return func(_ T) (bool, error) { return !v, nil } 102 }