From 13757e60c6d2c755fd2298f32260de8d4f17a482 Mon Sep 17 00:00:00 2001 From: yangyile Date: Mon, 25 Nov 2024 11:43:59 +0700 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 182 +++++++++++++++++++++++++++++++++++++++++++- terngo/znew.go | 17 +++++ terngo/znew_test.go | 30 ++++++++ terngo/zset.go | 15 ++++ terngo/zset_test.go | 52 +++++++++++++ 5 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 terngo/znew.go create mode 100644 terngo/znew_test.go create mode 100644 terngo/zset.go create mode 100644 terngo/zset_test.go diff --git a/README.md b/README.md index a471258..e942983 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,6 @@ The `tern` package provides the following functions based on condition types and | `FFV` | `func() bool` | Function returning value | Direct value | | `FFF` | `func() bool` | Function returning value | Function returning value | -Additionally, utility functions like `BV`, `BF`, `FV`, and `FF` simplify zero-value fallbacks. - ### Lazy Evaluation Example Using deferred execution ensures unnecessary computations are avoided: @@ -104,6 +102,186 @@ func main() { } ``` +以下是对 `BV`、`BF`、`FV` 和 `FF` 函数的详细表格说明: + +--- + +### Utility Functions for Zero-Value Fallbacks + +| **Function** | **Condition Type** | **Primary Value** | **Fallback Value** | **Description** | +|--------------|--------------------|--------------------------|------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| `BV` | `bool` | Direct value | Zero value of type `T` | Returns the first value if the condition is true, otherwise returns the zero value of type `T`. | +| `BF` | `bool` | Function returning value | Zero value of type `T` | Evaluates the function only if the condition is true, otherwise returns the zero value of type `T`. | +| `FV` | `func() bool` | Direct value | Zero value of type `T` | Evaluates the condition function and returns the first value if true, otherwise returns the zero value of type `T`. | +| `FF` | `func() bool` | Function returning value | Zero value of type `T` | Evaluates the condition function and returns the result of the first function if true, otherwise returns the zero value of type `T`. | + +--- + +### Examples + +#### Using `BV` + +```go +result := tern.BV(false, "value") +// Output: (empty string, as the condition is false) +``` + +#### Using `BF` + +```go +result := tern.BF(false, func() string { return "value" }) +// Output: (empty string, as the condition is false) +``` + +#### Using `FV` + +```go +condition := func() bool { return true } +result := tern.FV(condition, "value") +// Output: "value" (as the condition function returns true) +``` + +#### Using `FF` + +```go +condition := func() bool { return false } +result := tern.FF(condition, func() string { return "value" }) +// Output: (empty string, as the condition function returns false) +``` + +--- + +### Additional Utility Functions in `terngo` Package + +The `terngo` subpackage extends the functionality of `tern` with additional utility functions, specifically designed for comparing values to their zero value. These functions allow for more expressive handling of default values when one of the inputs might be zero. + +| **Function** | **Comparison Type** | **Primary Value** | **Fallback Value** | **Description** | +|--------------|---------------------|-------------------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| `VV` | Direct comparison | Direct value | Direct value | Returns the first value if it is not the zero value of type `T`, otherwise returns the second value. | +| `VF` | Direct comparison | Direct value | Function returning value | Returns the first value if it is not the zero value of type `T`, otherwise evaluates and returns the result of the fallback function. | + +--- + +### Examples + +#### Using `VV` + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern/terngo" +) + +func main() { + result := terngo.VV("non-zero", "fallback") + fmt.Println(result) // Output: "non-zero" + + result = terngo.VV("", "fallback") + fmt.Println(result) // Output: "fallback" +} +``` + +#### Using `VF` + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern/terngo" +) + +func main() { + fallbackFunc := func() string { return "fallback from func" } + + result := terngo.VF("non-zero", fallbackFunc) + fmt.Println(result) // Output: "non-zero" + + result = terngo.VF("", fallbackFunc) + fmt.Println(result) // Output: "fallback from func" +} +``` + +--- + +### Key Benefits of `VV` and `VF` + +- **Zero-Value Handling**: These functions leverage `tern.Zero[T]()` to check if the primary value is a zero value. +- **Fallback Options**: `VF` provides flexibility by allowing dynamic evaluation of the fallback value through a function. + +--- + +By including these functions in the `terngo` package, developers gain even more expressive tools to simplify conditional logic in Go. + +### Additional Utility Functions for Pointer Modification in `terngo` + +The `terngo` subpackage introduces `PV` and `PF`, two specialized functions for safely modifying a pointer's value when it holds the zero value of its type. These functions ensure safer and more expressive manipulation of pointers while providing fallback options. + +| **Function** | **Pointer Check** | **Fallback Value** | **Description** | +|--------------|-------------------------|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| `PV` | Pointer to direct value | Direct value | Sets the pointed-to value to the fallback value if it is the zero value of type `T`. Panics if the pointer is `nil`. | +| `PF` | Pointer to direct value | Function returning value | Sets the pointed-to value to the result of the fallback function if it is the zero value of type `T`. Panics if the pointer is `nil`. | + +--- + +### Examples + +#### Using `PV` + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern/terngo" +) + +func main() { + var value int + terngo.PV(&value, 42) + fmt.Println(value) // Output: 42 + + value = 7 + terngo.PV(&value, 99) + fmt.Println(value) // Output: 7 +} +``` + +#### Using `PF` + +```go +package main + +import ( + "fmt" + "github.com/yyle88/tern/terngo" +) + +func main() { + var value int + fallbackFunc := func() int { return 42 } + + terngo.PF(&value, fallbackFunc) + fmt.Println(value) // Output: 42 + + value = 7 + terngo.PF(&value, fallbackFunc) + fmt.Println(value) // Output: 7 +} +``` + +--- + +### Key Features of `PV` and `PF` + +- **Pointer Safety**: These functions panic if the provided pointer is `nil`, ensuring reliable execution. +- **Zero-Value Check**: Use `tern.Zero[T]()` to determine whether the current value is the zero value of its type. +- **Dynamic Fallback**: `PF` allows for fallback values to be generated dynamically via a function. + +By leveraging `PV` and `PF`, developers can seamlessly handle zero-value assignments for pointer-based logic, maintaining both clarity and robustness in their Go code. + ## Why Use `tern`? 1. **Readability**: Simplifies conditional logic, making the code easier to follow. diff --git a/terngo/znew.go b/terngo/znew.go new file mode 100644 index 0000000..9376e80 --- /dev/null +++ b/terngo/znew.go @@ -0,0 +1,17 @@ +package terngo + +import "github.com/yyle88/tern" + +func VV[T comparable](a T, b T) T { + if a != tern.Zero[T]() { + return a + } + return b +} + +func VF[T comparable](a T, b func() T) T { + if a != tern.Zero[T]() { + return a + } + return b() +} diff --git a/terngo/znew_test.go b/terngo/znew_test.go new file mode 100644 index 0000000..6d19e65 --- /dev/null +++ b/terngo/znew_test.go @@ -0,0 +1,30 @@ +package terngo_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/yyle88/tern/terngo" +) + +func TestVV(t *testing.T) { + require.Equal(t, 1, terngo.VV(0, 1)) + require.Equal(t, 1, terngo.VV(1, 2)) + require.Equal(t, "a", terngo.VV("", "a")) + require.Equal(t, "a", terngo.VV("a", "b")) +} + +func TestVF(t *testing.T) { + require.Equal(t, 1, terngo.VF(0, func() int { + return 1 + })) + require.Equal(t, 1, terngo.VF(1, func() int { + return 2 + })) + require.Equal(t, "a", terngo.VF("", func() string { + return "a" + })) + require.Equal(t, "a", terngo.VF("a", func() string { + return "b" + })) +} diff --git a/terngo/zset.go b/terngo/zset.go new file mode 100644 index 0000000..6402db9 --- /dev/null +++ b/terngo/zset.go @@ -0,0 +1,15 @@ +package terngo + +import "github.com/yyle88/tern" + +func PV[T comparable](p *T, b T) { + if *p == tern.Zero[T]() { + *p = b + } +} + +func PF[T comparable](p *T, b func() T) { + if *p == tern.Zero[T]() { + *p = b() + } +} diff --git a/terngo/zset_test.go b/terngo/zset_test.go new file mode 100644 index 0000000..3291250 --- /dev/null +++ b/terngo/zset_test.go @@ -0,0 +1,52 @@ +package terngo_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/yyle88/tern/terngo" +) + +func TestPV(t *testing.T) { + a := 0 + terngo.PV(&a, 1) + require.Equal(t, 1, a) + + b := 1 + terngo.PV(&b, 2) + require.Equal(t, 1, b) + + c := "" + terngo.PV(&c, "a") + require.Equal(t, "a", c) + + s := "a" + terngo.PV(&s, "b") + require.Equal(t, "a", s) +} + +func TestPF(t *testing.T) { + a := 0 + terngo.PF(&a, func() int { + return 1 + }) + require.Equal(t, 1, a) + + b := 1 + terngo.PF(&b, func() int { + return 2 + }) + require.Equal(t, 1, b) + + c := "" + terngo.PF(&c, func() string { + return "a" + }) + require.Equal(t, "a", c) + + s := "a" + terngo.PF(&s, func() string { + return "b" + }) + require.Equal(t, "a", s) +}