Skip to content

Commit

Permalink
Function: AcceptIf (#198)
Browse files Browse the repository at this point in the history
AcceptIf returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure.
A predicate function that takes an argument of type T and returns a bool.
An apply function that also takes an argument of type T and returns a modified value of the same type.
  • Loading branch information
donutloop committed Mar 4, 2024
1 parent aabfcb7 commit e138043
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 0 deletions.
53 changes: 53 additions & 0 deletions docs/api/packages/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [AcceptIf](#AcceptIf)


<div STYLE="page-break-after: always;"></div>

Expand Down Expand Up @@ -638,4 +640,55 @@ func main() {
// true
// false
}
```

### <span id="AcceptIf">AcceptIf</span>

<p>TBD</p>

<b>函数签名:</b>

```go
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool)
```

<b>示例:</b>

```go
package main

import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)

func main() {

adder := AcceptIf(
And(
func(x int) bool {
return x > 10
}, func(x int) bool {
return x%2 == 0
}),
func(x int) int {
return x + 1
},
)

result, ok := adder(20)
fmt.Println(result)
fmt.Println(ok)

result, ok = adder(21)
fmt.Println(result)
fmt.Println(ok)

// Output:
// 21
// true
// 0
// false
}

```
54 changes: 54 additions & 0 deletions docs/en/api/packages/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [AcceptIf](#AcceptIf)

<div STYLE="page-break-after: always;"></div>

Expand Down Expand Up @@ -638,4 +639,57 @@ func main() {
// true
// false
}
```

### <span id="AcceptIf">AcceptIf</span>

<p>AcceptIf returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure.
A predicate function that takes an argument of type T and returns a bool.
An apply function that also takes an argument of type T and returns a modified value of the same type.</p>

<b>Signature:</b>

```go
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool)
```

<b>Example:</b>

```go
package main

import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)

func main() {

adder := AcceptIf(
And(
func(x int) bool {
return x > 10
}, func(x int) bool {
return x%2 == 0
}),
func(x int) int {
return x + 1
},
)

result, ok := adder(20)
fmt.Println(result)
fmt.Println(ok)

result, ok = adder(21)
fmt.Println(result)
fmt.Println(ok)

// Output:
// 21
// true
// 0
// false
}

```
21 changes: 21 additions & 0 deletions function/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,27 @@ func Pipeline[T any](funcs ...func(T) T) func(T) T {
}
}

// AcceptIf returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure.
// A predicate function that takes an argument of type T and returns a bool.
// An apply function that also takes an argument of type T and returns a modified value of the same type.
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool) {
if predicate == nil {
panic("programming error: predicate must be not nil")
}

if apply == nil {
panic("programming error: apply must be not nil")
}

return func(t T) (T, bool) {
if !predicate(t) {
var defaultValue T
return defaultValue, false
}
return apply(t), true
}
}

func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args))
Expand Down
29 changes: 29 additions & 0 deletions function/function_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,32 @@ func ExamplePipeline() {
// Output:
// 36
}

func ExampleAcceptIf() {

adder := AcceptIf(
And(
func(x int) bool {
return x > 10
}, func(x int) bool {
return x%2 == 0
}),
func(x int) int {
return x + 1
},
)

result, ok := adder(20)
fmt.Println(result)
fmt.Println(ok)

result, ok = adder(21)
fmt.Println(result)
fmt.Println(ok)

// Output:
// 21
// true
// 0
// false
}
60 changes: 60 additions & 0 deletions function/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,63 @@ func TestPipeline(t *testing.T) {

assert.Equal(36, f(2))
}

func TestAcceptIf(t *testing.T) {
assert := internal.NewAssert(t, "AcceptIf")

adder := AcceptIf(
And(
func(x int) bool {
return x > 10
}, func(x int) bool {
return x%2 == 0
}),
func(x int) int {
return x + 1
},
)

result, ok := adder(20)
assert.Equal(21, result)
assert.Equal(true, ok)

result, ok = adder(21)
assert.Equal(0, result)
assert.Equal(false, ok)
}

func TestAcceptIfPanicMissingPredicate(t *testing.T) {
t.Parallel()

assert := internal.NewAssert(t, "TestAcceptIfPanicMissingPredicate")

defer func() {
v := recover()
assert.Equal("programming error: predicate must be not nil", v)
}()

AcceptIf(
nil,
func(x int) int {
return x
},
)
}

func TestAcceptIfPanicMissingApply(t *testing.T) {
t.Parallel()

assert := internal.NewAssert(t, "TestAcceptIfPanicMissingApply")

defer func() {
v := recover()
assert.Equal("programming error: apply must be not nil", v)
}()

AcceptIf(
func(i int) bool {
return false
},
nil,
)
}

0 comments on commit e138043

Please sign in to comment.