-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
calvin
committed
Jul 13, 2022
1 parent
c8073c8
commit 9504f98
Showing
11 changed files
with
348 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package sugar | ||
|
||
import "sync" | ||
|
||
type synchronize struct { | ||
locker sync.Locker | ||
} | ||
|
||
func (s *synchronize) Do(cb func() error) { | ||
s.locker.Lock() | ||
Try(cb) | ||
s.locker.Unlock() | ||
} | ||
|
||
func Synchronize(opt ...sync.Locker) synchronize { | ||
if len(opt) > 1 { | ||
panic("unexpected arguments") | ||
} else if len(opt) == 0 { | ||
opt = append(opt, &sync.Mutex{}) | ||
} | ||
|
||
return synchronize{locker: opt[0]} | ||
} | ||
|
||
func Async[A any](f func() A) chan A { | ||
ch := make(chan A) | ||
|
||
go func() { | ||
ch <- f() | ||
}() | ||
|
||
return ch | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package sugar | ||
|
||
func Ternary[T any](condition bool, ifOutput T, elseOutput T) T { | ||
|
||
if condition { | ||
return ifOutput | ||
} | ||
|
||
return elseOutput | ||
} | ||
|
||
type IfElse[T any] struct { | ||
Result T | ||
Ok bool | ||
} | ||
|
||
func If[T any](condition bool, result T) *IfElse[T] { | ||
|
||
if condition { | ||
return &IfElse[T]{result, true} | ||
} | ||
|
||
var t T | ||
return &IfElse[T]{t, false} | ||
} | ||
|
||
func IfFn[T any](condition bool, resultFn func() T) *IfElse[T] { | ||
|
||
if condition { | ||
return &IfElse[T]{resultFn(), true} | ||
} | ||
|
||
var t T | ||
return &IfElse[T]{t, false} | ||
} | ||
|
||
func (i *IfElse[T]) ElseIf(condition bool, result T) *IfElse[T] { | ||
|
||
if condition && !i.Ok { | ||
i.Result = result | ||
i.Ok = true | ||
} | ||
|
||
return i | ||
} | ||
|
||
func (i *IfElse[T]) ElseIfFn(condition bool, resultFn func() T) *IfElse[T] { | ||
if condition && !i.Ok { | ||
i.Result = resultFn() | ||
i.Ok = true | ||
} | ||
|
||
return i | ||
} | ||
|
||
func (i *IfElse[T]) Else(result T) T { | ||
if i.Ok { | ||
return i.Result | ||
} | ||
|
||
return result | ||
} | ||
|
||
func (i *IfElse[T]) ElseFn(resultFn func() T) T { | ||
if i.Ok { | ||
return i.Result | ||
} | ||
|
||
return resultFn() | ||
} | ||
|
||
type SwitchCase[T comparable, R any] struct { | ||
Predicate T | ||
Result R | ||
Ok bool | ||
} | ||
|
||
func Switch[T comparable, R any](predicate T) *SwitchCase[T, R] { | ||
var result R | ||
|
||
return &SwitchCase[T, R]{ | ||
predicate, | ||
result, | ||
false, | ||
} | ||
} | ||
|
||
func (s *SwitchCase[T, R]) Case(value T, result R) *SwitchCase[T, R] { | ||
if !s.Ok && s.Predicate == value { | ||
s.Result = result | ||
s.Ok = true | ||
} | ||
return s | ||
} | ||
|
||
func (s *SwitchCase[T, R]) CaseFn(value T, resultFn func() R) *SwitchCase[T, R] { | ||
if !s.Ok && value == s.Predicate { | ||
s.Result = resultFn() | ||
s.Ok = true | ||
} | ||
|
||
return s | ||
} | ||
|
||
func (s *SwitchCase[T, R]) Default(result R) R { | ||
if !s.Ok { | ||
s.Result = result | ||
} | ||
|
||
return s.Result | ||
} | ||
|
||
func (s *SwitchCase[T, R]) DefaultFn(resultFn func() R) R { | ||
if !s.Ok { | ||
s.Result = resultFn() | ||
} | ||
|
||
return s.Result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package sugar | ||
|
||
//Try calls the function and return false in case of error. | ||
func Try(callback func() error) (ok bool) { | ||
ok = true | ||
|
||
defer func() { | ||
if err := recover(); err != nil { | ||
ok = false | ||
return | ||
} | ||
}() | ||
|
||
err := callback() | ||
if err != nil { | ||
ok = false | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package sugar | ||
|
||
func IndexOf[T comparable](collection []T, predicate func(T) bool) int { | ||
for i, t := range collection { | ||
if predicate(t) { | ||
return i | ||
} | ||
} | ||
|
||
return -1 | ||
} | ||
|
||
func LastIndexOf[T comparable](collection []T, predicate func(T) bool) int { | ||
l := len(collection) | ||
|
||
for i := l - 1; i >= 0; i-- { | ||
if predicate(collection[i]) { | ||
return i | ||
} | ||
} | ||
|
||
return -1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module sugar | ||
|
||
go 1.18 | ||
|
||
require golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 h1:x03zeu7B2B11ySp+daztnwM5oBJ/8wGUSqrwcw9L0RA= | ||
golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package sugar | ||
|
||
import ( | ||
"golang.org/x/exp/constraints" | ||
) | ||
|
||
//Clamp clamps number within the inclusive lower and upper bounds. | ||
func Clamp[T constraints.Ordered](value, min, max T) T { | ||
if value < min { | ||
value = min | ||
} else if value > max { | ||
value = max | ||
} | ||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package sugar | ||
|
||
import ( | ||
"sync" | ||
"time" | ||
) | ||
|
||
type Debounce struct { | ||
after time.Duration | ||
mu *sync.Mutex | ||
timer *time.Timer | ||
done bool | ||
callbacks []func() | ||
} | ||
|
||
func NewDebounce(duration time.Duration, fns ...func()) (func(), func()) { | ||
d := &Debounce{ | ||
after: duration, | ||
mu: new(sync.Mutex), | ||
timer: nil, | ||
done: false, | ||
callbacks: fns, | ||
} | ||
return func() { | ||
d.reset() | ||
}, d.cancel | ||
} | ||
|
||
func (d *Debounce) reset() *Debounce { | ||
d.mu.Lock() | ||
defer d.mu.Unlock() | ||
if d.done { | ||
return d | ||
} | ||
if d.timer != nil { | ||
d.timer.Stop() | ||
} | ||
d.timer = time.AfterFunc(d.after, func() { | ||
for _, cb := range d.callbacks { | ||
cb() | ||
} | ||
}) | ||
return d | ||
} | ||
|
||
func (d *Debounce) cancel() { | ||
d.mu.Lock() | ||
defer d.mu.Unlock() | ||
if d.timer != nil { | ||
d.timer.Stop() | ||
d.timer = nil | ||
} | ||
d.done = true | ||
} | ||
|
||
// AttemptWithDelay invokes a function N times until it returns valid output, | ||
// with a pause between each call. Returning either the caught error or nil. | ||
// When first argument is less than `1`, the function runs until a successful | ||
// response is returned. | ||
|
||
func AttemptWithDelay(maxIteration int, delay time.Duration, f func(int, time.Duration) error) (int, time.Duration, error) { | ||
var err error | ||
start := time.Now() | ||
for i := 0; maxIteration <= 0 || i < maxIteration; i++ { | ||
err = f(i, time.Since(start)) | ||
if err == nil { | ||
return i + 1, time.Since(start), nil | ||
} | ||
if maxIteration <= 0 || i+1 < maxIteration { | ||
time.Sleep(delay) | ||
} | ||
} | ||
return maxIteration, time.Since(start), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package sugar | ||
|
||
func SliceFileter[V any](collection []V, fileter func(V, int) bool) []V { | ||
|
||
result := []V{} | ||
|
||
for i, v := range collection { | ||
if fileter(v, i) { | ||
result = append(result, v) | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
func SliceUpdateElement[T any, R any](collection []T, iteratee func(T, int) R) []R { | ||
result := make([]R, len(collection)) | ||
|
||
for i, t := range collection { | ||
result[i] = iteratee(t, i) | ||
} | ||
|
||
return result | ||
} | ||
|
||
func SliceUniq[T any, U comparable](collection []T, iteratee func(T) U) []T { | ||
result := make([]T, len(collection)) | ||
|
||
seen := make(map[U]struct{}, len(collection)) | ||
for _, item := range collection { | ||
key := iteratee(item) | ||
if _, ok := seen[key]; ok { | ||
continue | ||
} | ||
seen[key] = struct{}{} | ||
} | ||
|
||
return result | ||
} | ||
|
||
func SliceGroupBy[T any, U comparable](collection []T, iteratee func(T) U) map[U][]T { | ||
result := map[U][]T{} | ||
|
||
for _, item := range collection { | ||
key := iteratee(item) | ||
|
||
result[key] = append(result[key], item) | ||
} | ||
return result | ||
} |