diff --git a/pkg/utils/ifelse/ifelse.go b/pkg/utils/ifelse/ifelse.go index fce28401..2e1bc388 100644 --- a/pkg/utils/ifelse/ifelse.go +++ b/pkg/utils/ifelse/ifelse.go @@ -1,34 +1,84 @@ package ifelse +type branch[T any] struct { + cond bool + fn func() T +} + type ifExpr[T any] struct { - condition bool + cond bool } type thenExpr[T any] struct { - condition bool - consequent T + branches []branch[T] } -// 示例: +type elseIfExpr[T any] struct { + branches []branch[T] + cond bool +} + +// 用法示例: // -// result := ifelse.If[T](condition).Then(consequent).Else(alternative) +// result := ifelse.If[string](age < 18).Then("child"). +// ElseIf(age < 60).Then("adult"). +// ElseIf(age < 120).Then("senior"). +// Else("invalid") func If[T any](condition bool) *ifExpr[T] { - return &ifExpr[T]{ - condition: condition, - } + return &ifExpr[T]{cond: condition} } func (e *ifExpr[T]) Then(consequent T) *thenExpr[T] { return &thenExpr[T]{ - condition: e.condition, - consequent: consequent, + branches: []branch[T]{ + {cond: e.cond, fn: func() T { return consequent }}, + }, + } +} + +func (e *ifExpr[T]) ThenFunc(consequent func() T) *thenExpr[T] { + return &thenExpr[T]{ + branches: []branch[T]{ + {cond: e.cond, fn: consequent}, + }, + } +} + +func (e *thenExpr[T]) ElseIf(condition bool) *elseIfExpr[T] { + return &elseIfExpr[T]{ + branches: e.branches, + cond: condition, + } +} + +func (e *elseIfExpr[T]) Then(alternative T) *thenExpr[T] { + branch := branch[T]{cond: e.cond, fn: func() T { return alternative }} + return &thenExpr[T]{ + branches: append(e.branches, branch), + } +} + +func (e *elseIfExpr[T]) ThenFunc(alternativeFunc func() T) *thenExpr[T] { + branch := branch[T]{cond: e.cond, fn: alternativeFunc} + return &thenExpr[T]{ + branches: append(e.branches, branch), } } func (e *thenExpr[T]) Else(alternative T) T { - if e.condition { - return e.consequent + for _, b := range e.branches { + if b.cond { + return b.fn() + } } - return alternative } + +func (e *thenExpr[T]) ElseFunc(alternativeFunc func() T) T { + for _, b := range e.branches { + if b.cond { + return b.fn() + } + } + return alternativeFunc() +} diff --git a/pkg/utils/ifelse/ifelse_test.go b/pkg/utils/ifelse/ifelse_test.go new file mode 100644 index 00000000..51656487 --- /dev/null +++ b/pkg/utils/ifelse/ifelse_test.go @@ -0,0 +1,196 @@ +package ifelse_test + +import ( + "testing" + + "github.com/certimate-go/certimate/pkg/utils/ifelse" +) + +func TestIfTrue(t *testing.T) { + result := ifelse.If[string](true). + Then("true branch"). + Else("false branch") + + if result != "true branch" { + t.Errorf("Expected 'true branch', got '%s'", result) + } +} + +func TestIfFalse(t *testing.T) { + result := ifelse.If[string](false). + Then("true branch"). + Else("false branch") + + if result != "false branch" { + t.Errorf("Expected 'false branch', got '%s'", result) + } +} + +func TestElseIfFirstMatch(t *testing.T) { + result := ifelse.If[string](false). + Then("should not run"). + ElseIf(true). + Then("elseif branch"). + Else("should not run") + + if result != "elseif branch" { + t.Errorf("Expected 'elseif branch', got '%s'", result) + } +} + +func TestElseIfSecondMatch(t *testing.T) { + result := ifelse.If[string](false). + Then("should not run"). + ElseIf(false). + Then("should not run"). + ElseIf(true). + Then("second elseif"). + Else("should not run") + + if result != "second elseif" { + t.Errorf("Expected 'second elseif', got '%s'", result) + } +} + +func TestMultipleConditions(t *testing.T) { + result := ifelse.If[string](1 > 2). + Then("impossible"). + ElseIf(2+2 == 5). + Then("false math"). + ElseIf(3*3 == 9). + Then("correct math"). + Else("fallback") + + if result != "correct math" { + t.Errorf("Expected 'correct math', got '%s'", result) + } +} + +func TestAllConditionsFalse(t *testing.T) { + result := ifelse.If[int](false). + Then(1). + ElseIf(false). + Then(2). + ElseIf(false). + Then(3). + Else(99) + + if result != 99 { + t.Errorf("Expected 99, got %d", result) + } +} + +func TestLazyEvaluationThen(t *testing.T) { + called := []string{} + + result := ifelse.If[string](true). + ThenFunc(func() string { + called = append(called, "then") + return "then" + }). + ElseIf(true). + ThenFunc(func() string { + called = append(called, "elseif") + return "elseif" + }). + ElseFunc(func() string { + called = append(called, "else") + return "else" + }) + + // 验证结果和调用情况 + if result != "then" { + t.Errorf("Expected 'then', got '%s'", result) + } + + if len(called) != 1 || called[0] != "then" { + t.Errorf("Expected only 'then' called, got %v", called) + } +} + +func TestLazyEvaluationElseIf(t *testing.T) { + called := []string{} + + result := ifelse.If[string](false). + ThenFunc(func() string { + called = append(called, "then") + return "then" + }). + ElseIf(true). + ThenFunc(func() string { + called = append(called, "elseif") + return "elseif" + }). + ElseFunc(func() string { + called = append(called, "else") + return "else" + }) + + // 验证结果和调用情况 + if result != "elseif" { + t.Errorf("Expected 'elseif', got '%s'", result) + } + + if len(called) != 1 || called[0] != "elseif" { + t.Errorf("Expected only 'elseif' called, got %v", called) + } +} + +func TestLazyEvaluationElse(t *testing.T) { + called := []string{} + + result := ifelse.If[string](false). + ThenFunc(func() string { + called = append(called, "then") + return "then" + }). + ElseIf(false). + ThenFunc(func() string { + called = append(called, "elseif") + return "elseif" + }). + ElseFunc(func() string { + called = append(called, "else") + return "else" + }) + + // 验证结果和调用情况 + if result != "else" { + t.Errorf("Expected 'else', got '%s'", result) + } + + if len(called) != 1 || called[0] != "else" { + t.Errorf("Expected only 'else' called, got %v", called) + } +} + +func TestMixedValueAndFunc(t *testing.T) { + result := ifelse.If[int](false). + Then(0). + ElseIf(false). + ThenFunc(func() int { + return 1 + }). + ElseIf(true). + Then(2). + Else(3) + + if result != 2 { + t.Errorf("Expected 2, got %d", result) + } +} + +func TestComplexNumericLogic(t *testing.T) { + x := 15 + result := ifelse.If[string](x < 10). + Then("single digit"). + ElseIf(x < 20). + Then("teens"). + ElseIf(x < 30). + Then("twenties"). + Else("older") + + if result != "teens" { + t.Errorf("Expected 'teens', got '%s'", result) + } +}