mirror of
https://github.com/duke-git/lancet.git
synced 2025-10-17 21:11:26 +08:00
Add functional predicate (#171)
Enable the execution of assertion functions in a functional manner.
This commit is contained in:
34
function/predicate.go
Normal file
34
function/predicate.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
// And returns a composed predicate that represents the logical AND of a list of predicates.
|
||||||
|
// It evaluates to true only if all predicates evaluate to true for the given value.
|
||||||
|
func And[T any](predicates ...func(T) bool) func(T) bool {
|
||||||
|
return func(value T) bool {
|
||||||
|
for _, predicate := range predicates {
|
||||||
|
if !predicate(value) {
|
||||||
|
return false // Short-circuit on the first false predicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true // True if all predicates are true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negate returns a predicate that represents the logical negation of this predicate.
|
||||||
|
func Negate[T any](predicate func(T) bool) func(T) bool {
|
||||||
|
return func(value T) bool {
|
||||||
|
return !predicate(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or returns a composed predicate that represents the logical OR of a list of predicates.
|
||||||
|
// It evaluates to true if at least one of the predicates evaluates to true for the given value.
|
||||||
|
func Or[T any](predicates ...func(T) bool) func(T) bool {
|
||||||
|
return func(value T) bool {
|
||||||
|
for _, predicate := range predicates {
|
||||||
|
if predicate(value) {
|
||||||
|
return true // Short-circuit on the first true predicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false // False if all predicates are false
|
||||||
|
}
|
||||||
|
}
|
75
function/predicate_test.go
Normal file
75
function/predicate_test.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPredicatesNegatePure(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestPredicatesNegatePure")
|
||||||
|
|
||||||
|
// Define some simple predicates for demonstration
|
||||||
|
isUpperCase := func(s string) bool {
|
||||||
|
return strings.ToUpper(s) == s
|
||||||
|
}
|
||||||
|
isLowerCase := func(s string) bool {
|
||||||
|
return strings.ToLower(s) == s
|
||||||
|
}
|
||||||
|
isMixedCase := Negate(Or(isUpperCase, isLowerCase))
|
||||||
|
|
||||||
|
assert.ShouldBeFalse(isMixedCase("ABC"))
|
||||||
|
assert.ShouldBeTrue(isMixedCase("AbC"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPredicatesOrPure(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestPredicatesOrPure")
|
||||||
|
|
||||||
|
containsDigitOrSpecialChar := Or(
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "!@#$%") },
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ShouldBeTrue(containsDigitOrSpecialChar("hello!"))
|
||||||
|
assert.ShouldBeFalse(containsDigitOrSpecialChar("hello"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPredicatesAndPure(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestPredicatesAndPure")
|
||||||
|
|
||||||
|
isNumericAndLength5 := And(
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||||
|
func(s string) bool { return len(s) == 5 },
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ShouldBeTrue(isNumericAndLength5("12345"))
|
||||||
|
assert.ShouldBeFalse(isNumericAndLength5("1234"))
|
||||||
|
assert.ShouldBeFalse(isNumericAndLength5("abcde"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPredicatesMix(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestPredicatesMix")
|
||||||
|
|
||||||
|
a := Or(
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "!") },
|
||||||
|
)
|
||||||
|
|
||||||
|
b := And(
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "hello") },
|
||||||
|
func(s string) bool { return strings.ContainsAny(s, "!") },
|
||||||
|
)
|
||||||
|
|
||||||
|
c := Negate(And(a, b))
|
||||||
|
|
||||||
|
assert.ShouldBeFalse(c("hello!"))
|
||||||
|
}
|
Reference in New Issue
Block a user