Commit a05c795

mo khan <mo@mokhan.ca>
2025-04-24 23:47:27
feat: add specification interface
1 parent b1595f0
pkg/x/specification.go
@@ -0,0 +1,21 @@
+package x
+
+type Specification[T any] interface {
+	IsSatisfiedBy(T) bool
+}
+
+func (f Predicate[T]) IsSatisfiedBy(item T) bool {
+	return f(item)
+}
+
+func (s Predicate[T]) Or(other Specification[T]) Predicate[T] {
+	return Predicate[T](func(item T) bool {
+		return s.IsSatisfiedBy(item) || other.IsSatisfiedBy(item)
+	})
+}
+
+func (s Predicate[T]) And(other Specification[T]) Predicate[T] {
+	return Predicate[T](func(item T) bool {
+		return s.IsSatisfiedBy(item) && other.IsSatisfiedBy(item)
+	})
+}
pkg/x/specification_test.go
@@ -0,0 +1,57 @@
+package x
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestFuncSpecification(t *testing.T) {
+	even := Predicate[int](func(item int) bool {
+		return item%2 == 0
+	})
+
+	odd := Predicate[int](func(item int) bool {
+		return !even.IsSatisfiedBy(item)
+	})
+
+	greaterThan := func(max int) Specification[int] {
+		return Predicate[int](func(i int) bool {
+			return i > max
+		})
+	}
+
+	t.Run("IsSatisfiedBy", func(t *testing.T) {
+		assert.True(t, even.IsSatisfiedBy(2))
+		assert.False(t, even.IsSatisfiedBy(1))
+
+		assert.True(t, odd.IsSatisfiedBy(1))
+		assert.False(t, odd.IsSatisfiedBy(2))
+	})
+
+	t.Run("Or", func(t *testing.T) {
+		assert.True(t, even.Or(greaterThan(3)).IsSatisfiedBy(2))
+		assert.True(t, even.Or(greaterThan(3)).IsSatisfiedBy(5))
+		assert.False(t, even.Or(greaterThan(3)).IsSatisfiedBy(3))
+		assert.False(t, even.Or(greaterThan(3)).IsSatisfiedBy(1))
+	})
+
+	t.Run("And", func(t *testing.T) {
+		assert.True(t, even.And(greaterThan(10)).IsSatisfiedBy(12))
+		assert.False(t, even.And(greaterThan(10)).IsSatisfiedBy(8))
+	})
+
+	p := Predicate[int](func(item int) bool {
+		return item == 1
+	}).Or(Predicate[int](func(item int) bool {
+		return item == 2
+	})).Or(Predicate[int](func(item int) bool {
+		return item == 3
+	}))
+
+	assert.False(t, p.IsSatisfiedBy(0))
+	assert.True(t, p.IsSatisfiedBy(1))
+	assert.True(t, p.IsSatisfiedBy(2))
+	assert.True(t, p.IsSatisfiedBy(3))
+	assert.False(t, p.IsSatisfiedBy(4))
+}