From b803f8aa23b9cb7d9d9dc0204555f7158e085a47 Mon Sep 17 00:00:00 2001 From: wirekang Date: Wed, 20 Apr 2022 22:25:22 +0900 Subject: [PATCH 1/4] Add #96 --- find.go | 13 ++++++++++++ find_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/find.go b/find.go index e7d50bde..81e068cc 100644 --- a/find.go +++ b/find.go @@ -237,3 +237,16 @@ func Samples[T any](collection []T, count int) []T { return results } + +// Coalesce returns the first non-default arguments. Arguments must be comparable. +func Coalesce[T comparable](v ...T) (result T, ok bool) { + for _, e := range v { + if e != result { + result = e + ok = true + return + } + } + + return +} diff --git a/find_test.go b/find_test.go index 6e6a1661..64dd5125 100644 --- a/find_test.go +++ b/find_test.go @@ -214,3 +214,61 @@ func TestSamples(t *testing.T) { is.Equal(result1, []string{"a", "b", "c"}) is.Equal(result2, []string{}) } + +func TestCoalesce(t *testing.T) { + is := assert.New(t) + + newStr := func(v string) *string { return &v } + var nilStr *string + str1 := newStr("str1") + str2 := newStr("str2") + + type structType struct { + field1 int + field2 float64 + } + var zeroStruct structType + struct1 := structType{1, 1.0} + struct2 := structType{2, 2.0} + + result1, ok1 := Coalesce[int]() + result2, ok2 := Coalesce(3) + result3, ok3 := Coalesce[*string](nil, nilStr) + result4, ok4 := Coalesce(nilStr, str1) + result5, ok5 := Coalesce(nilStr, str1, str2) + result6, ok6 := Coalesce(str1, str2, nilStr) + result7, ok7 := Coalesce(0, 1, 2, 3) + result8, ok8 := Coalesce(zeroStruct) + result9, ok9 := Coalesce(zeroStruct, struct1) + result10, ok10 := Coalesce(zeroStruct, struct1, struct2) + + is.Equal(0, result1) + is.False(ok1) + + is.Equal(3, result2) + is.True(ok2) + + is.Nil(result3) + is.False(ok3) + + is.Equal(str1, result4) + is.True(ok4) + + is.Equal(str1, result5) + is.True(ok5) + + is.Equal(str1, result6) + is.True(ok6) + + is.Equal(result7, 1) + is.True(ok7) + + is.Equal(result8, zeroStruct) + is.False(ok8) + + is.Equal(result9, struct1) + is.True(ok9) + + is.Equal(result10, struct1) + is.True(ok10) +} From dff318b485287c6993f18bf243695fc1b1b69d89 Mon Sep 17 00:00:00 2001 From: Samuel Berthe Date: Thu, 21 Apr 2022 17:19:25 +0200 Subject: [PATCH 2/4] doc(coalesce): adding doc for this new helper --- README.md | 18 +++++++++++++++ find.go | 16 ++----------- find_test.go | 58 ------------------------------------------------ pointers.go | 15 ++++++++++++- pointers_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 109a790e..89495dc8 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,7 @@ Other functional programming helpers: - ToPtr - ToSlicePtr - Empty +- Coalesce Concurrency helpers: @@ -1161,6 +1162,23 @@ lo.Empty[bool]() // false ``` +### Coalesce + +Returns the first non-empty arguments. Arguments must be comparable. + +```go +result, ok := Coalesce(0, 1, 2, 3) +// 1 true + +result, ok := Coalesce("") +// "" false + +var nilStr *string +str := "foobar" +result, ok := Coalesce[*string](nil, nilStr, &str) +// &"foobar" true +``` + ### Attempt Invokes a function N times until it returns valid output. Returning either the caught error or nil. When first argument is less than `1`, the function runs until a sucessfull response is returned. diff --git a/find.go b/find.go index 81e068cc..8f24e238 100644 --- a/find.go +++ b/find.go @@ -2,9 +2,10 @@ package lo import ( "fmt" - "golang.org/x/exp/constraints" "math" "math/rand" + + "golang.org/x/exp/constraints" ) // import "golang.org/x/exp/constraints" @@ -237,16 +238,3 @@ func Samples[T any](collection []T, count int) []T { return results } - -// Coalesce returns the first non-default arguments. Arguments must be comparable. -func Coalesce[T comparable](v ...T) (result T, ok bool) { - for _, e := range v { - if e != result { - result = e - ok = true - return - } - } - - return -} diff --git a/find_test.go b/find_test.go index 64dd5125..6e6a1661 100644 --- a/find_test.go +++ b/find_test.go @@ -214,61 +214,3 @@ func TestSamples(t *testing.T) { is.Equal(result1, []string{"a", "b", "c"}) is.Equal(result2, []string{}) } - -func TestCoalesce(t *testing.T) { - is := assert.New(t) - - newStr := func(v string) *string { return &v } - var nilStr *string - str1 := newStr("str1") - str2 := newStr("str2") - - type structType struct { - field1 int - field2 float64 - } - var zeroStruct structType - struct1 := structType{1, 1.0} - struct2 := structType{2, 2.0} - - result1, ok1 := Coalesce[int]() - result2, ok2 := Coalesce(3) - result3, ok3 := Coalesce[*string](nil, nilStr) - result4, ok4 := Coalesce(nilStr, str1) - result5, ok5 := Coalesce(nilStr, str1, str2) - result6, ok6 := Coalesce(str1, str2, nilStr) - result7, ok7 := Coalesce(0, 1, 2, 3) - result8, ok8 := Coalesce(zeroStruct) - result9, ok9 := Coalesce(zeroStruct, struct1) - result10, ok10 := Coalesce(zeroStruct, struct1, struct2) - - is.Equal(0, result1) - is.False(ok1) - - is.Equal(3, result2) - is.True(ok2) - - is.Nil(result3) - is.False(ok3) - - is.Equal(str1, result4) - is.True(ok4) - - is.Equal(str1, result5) - is.True(ok5) - - is.Equal(str1, result6) - is.True(ok6) - - is.Equal(result7, 1) - is.True(ok7) - - is.Equal(result8, zeroStruct) - is.False(ok8) - - is.Equal(result9, struct1) - is.True(ok9) - - is.Equal(result10, struct1) - is.True(ok10) -} diff --git a/pointers.go b/pointers.go index 02bbdfa9..623d547d 100644 --- a/pointers.go +++ b/pointers.go @@ -7,7 +7,7 @@ func ToPtr[T any](x T) *T { // ToSlicePtr returns a slice of pointer copy of value. func ToSlicePtr[T any](collection []T) []*T { - return Map(collection, func (x T, _ int) *T { + return Map(collection, func(x T, _ int) *T { return &x }) } @@ -17,3 +17,16 @@ func Empty[T any]() T { var t T return t } + +// Coalesce returns the first non-empty arguments. Arguments must be comparable. +func Coalesce[T comparable](v ...T) (result T, ok bool) { + for _, e := range v { + if e != result { + result = e + ok = true + return + } + } + + return +} diff --git a/pointers_test.go b/pointers_test.go index 21937d88..b6215837 100644 --- a/pointers_test.go +++ b/pointers_test.go @@ -23,3 +23,61 @@ func TestToSlicePtr(t *testing.T) { is.Equal(result1, []*string{&str1, &str2}) } + +func TestCoalesce(t *testing.T) { + is := assert.New(t) + + newStr := func(v string) *string { return &v } + var nilStr *string + str1 := newStr("str1") + str2 := newStr("str2") + + type structType struct { + field1 int + field2 float64 + } + var zeroStruct structType + struct1 := structType{1, 1.0} + struct2 := structType{2, 2.0} + + result1, ok1 := Coalesce[int]() + result2, ok2 := Coalesce(3) + result3, ok3 := Coalesce[*string](nil, nilStr) + result4, ok4 := Coalesce(nilStr, str1) + result5, ok5 := Coalesce(nilStr, str1, str2) + result6, ok6 := Coalesce(str1, str2, nilStr) + result7, ok7 := Coalesce(0, 1, 2, 3) + result8, ok8 := Coalesce(zeroStruct) + result9, ok9 := Coalesce(zeroStruct, struct1) + result10, ok10 := Coalesce(zeroStruct, struct1, struct2) + + is.Equal(0, result1) + is.False(ok1) + + is.Equal(3, result2) + is.True(ok2) + + is.Nil(result3) + is.False(ok3) + + is.Equal(str1, result4) + is.True(ok4) + + is.Equal(str1, result5) + is.True(ok5) + + is.Equal(str1, result6) + is.True(ok6) + + is.Equal(result7, 1) + is.True(ok7) + + is.Equal(result8, zeroStruct) + is.False(ok8) + + is.Equal(result9, struct1) + is.True(ok9) + + is.Equal(result10, struct1) + is.True(ok10) +} From 1ede5e188f4e3b65eb36db505d22beb7a577c3d2 Mon Sep 17 00:00:00 2001 From: Muhan Li Date: Fri, 22 Apr 2022 16:58:55 +0800 Subject: [PATCH 3/4] fix wrong examples of Clamp function --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 89495dc8..822d687b 100644 --- a/README.md +++ b/README.md @@ -748,13 +748,13 @@ Clamps number within the inclusive lower and upper bounds. ```go r1 := lo.Clamp(0, -10, 10) -// 10 +// 0 r2 := lo.Clamp(-42, -10, 10) -// -42 +// -10 r3 := lo.Clamp(42, -10, 10) -// 42 +// 10 ``` ### T2 -> T9 @@ -841,7 +841,7 @@ Returns the difference between two collections. left, right := lo.Difference[int]([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 6}) // []int{1, 3, 4, 5}, []int{6} -left, right := Difference[int]([]int{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3, 4, 5}) +left, right := lo.Difference[int]([]int{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3, 4, 5}) // []int{}, []int{} ``` From 6d64c8b195d76bafa77c4e252c0836de0c406478 Mon Sep 17 00:00:00 2001 From: wirekang Date: Fri, 22 Apr 2022 01:11:24 +0900 Subject: [PATCH 4/4] Fix typo --- errors.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/errors.go b/errors.go index f27373bc..c94c52eb 100644 --- a/errors.go +++ b/errors.go @@ -22,7 +22,7 @@ func Must1[T any](val T, err error) T { return Must(val, err) } -// Must2 has the same behavior than Must, but callback returns 2 variable2. +// Must2 has the same behavior than Must, but callback returns 2 variables. func Must2[T1 any, T2 any](val1 T1, val2 T2, err error) (T1, T2) { if err != nil { panic(err) @@ -31,7 +31,7 @@ func Must2[T1 any, T2 any](val1 T1, val2 T2, err error) (T1, T2) { return val1, val2 } -// Must3 has the same behavior than Must, but callback returns 2 variable2. +// Must3 has the same behavior than Must, but callback returns 3 variables. func Must3[T1 any, T2 any, T3 any](val1 T1, val2 T2, val3 T3, err error) (T1, T2, T3) { if err != nil { panic(err) @@ -40,7 +40,7 @@ func Must3[T1 any, T2 any, T3 any](val1 T1, val2 T2, val3 T3, err error) (T1, T2 return val1, val2, val3 } -// Must4 has the same behavior than Must, but callback returns 2 variable2. +// Must4 has the same behavior than Must, but callback returns 4 variables. func Must4[T1 any, T2 any, T3 any, T4 any](val1 T1, val2 T2, val3 T3, val4 T4, err error) (T1, T2, T3, T4) { if err != nil { panic(err) @@ -49,7 +49,7 @@ func Must4[T1 any, T2 any, T3 any, T4 any](val1 T1, val2 T2, val3 T3, val4 T4, e return val1, val2, val3, val4 } -// Must5 has the same behavior than Must, but callback returns 2 variable2. +// Must5 has the same behavior than Must, but callback returns 5 variables. func Must5[T1 any, T2 any, T3 any, T4 any, T5 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, err error) (T1, T2, T3, T4, T5) { if err != nil { panic(err) @@ -58,7 +58,7 @@ func Must5[T1 any, T2 any, T3 any, T4 any, T5 any](val1 T1, val2 T2, val3 T3, va return val1, val2, val3, val4, val5 } -// Must6 has the same behavior than Must, but callback returns 2 variable2. +// Must6 has the same behavior than Must, but callback returns 6 variables. func Must6[T1 any, T2 any, T3 any, T4 any, T5 any, T6 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, val6 T6, err error) (T1, T2, T3, T4, T5, T6) { if err != nil { panic(err)