mirror of
https://github.com/duke-git/lancet.git
synced 2025-09-27 11:52:25 +08:00
126 lines
2.9 KiB
Go
126 lines
2.9 KiB
Go
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
|
// Use of this source code is governed by MIT license
|
|
|
|
// Package function implements some functions for control the function execution and some is for functional programming.
|
|
package function
|
|
|
|
import (
|
|
"reflect"
|
|
"time"
|
|
)
|
|
|
|
// After creates a function that invokes func once it's called n or more times
|
|
func After(n int, fn any) func(args ...any) []reflect.Value {
|
|
// Catch programming error while constructing the closure
|
|
mustBeFunction(fn)
|
|
|
|
return func(args ...any) []reflect.Value {
|
|
n--
|
|
if n < 1 {
|
|
return unsafeInvokeFunc(fn, args...)
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Before creates a function that invokes func once it's called less than n times
|
|
func Before(n int, fn any) func(args ...any) []reflect.Value {
|
|
// Catch programming error while constructing the closure
|
|
mustBeFunction(fn)
|
|
var result []reflect.Value
|
|
return func(args ...any) []reflect.Value {
|
|
if n > 0 {
|
|
result = unsafeInvokeFunc(fn, args...)
|
|
}
|
|
if n <= 0 {
|
|
fn = nil
|
|
}
|
|
n--
|
|
return result
|
|
}
|
|
}
|
|
|
|
// Fn is for curry function which is func(...any) any
|
|
type Fn func(...any) any
|
|
|
|
// Curry make a curry function
|
|
func (f Fn) Curry(i any) func(...any) any {
|
|
return func(values ...any) any {
|
|
v := append([]any{i}, values...)
|
|
return f(v...)
|
|
}
|
|
}
|
|
|
|
// Compose compose the functions from right to left
|
|
func Compose(fnList ...func(...any) any) func(...any) any {
|
|
return func(s ...any) any {
|
|
f := fnList[0]
|
|
restFn := fnList[1:]
|
|
|
|
if len(fnList) == 1 {
|
|
return f(s...)
|
|
}
|
|
|
|
return f(Compose(restFn...)(s...))
|
|
}
|
|
}
|
|
|
|
// Delay make the function execution after delayed time
|
|
func Delay(delay time.Duration, fn any, args ...any) {
|
|
// Catch programming error while constructing the closure
|
|
mustBeFunction(fn)
|
|
|
|
time.Sleep(delay)
|
|
invokeFunc(fn, args...)
|
|
}
|
|
|
|
// Debounced creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
|
|
func Debounced(fn func(), duration time.Duration) func() {
|
|
// Catch programming error while constructing the closure
|
|
mustBeFunction(fn)
|
|
|
|
timer := time.NewTimer(duration)
|
|
timer.Stop()
|
|
|
|
go func() {
|
|
for {
|
|
<-timer.C
|
|
go fn()
|
|
}
|
|
}()
|
|
|
|
return func() { timer.Reset(duration) }
|
|
}
|
|
|
|
// Schedule invoke function every duration time, util close the returned bool chan
|
|
func Schedule(d time.Duration, fn any, args ...any) chan bool {
|
|
// Catch programming error while constructing the closure
|
|
mustBeFunction(fn)
|
|
|
|
quit := make(chan bool)
|
|
go func() {
|
|
for {
|
|
unsafeInvokeFunc(fn, args...)
|
|
select {
|
|
case <-time.After(d):
|
|
case <-quit:
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
return quit
|
|
}
|
|
|
|
// Pipeline takes a list of functions and returns a function whose param will be passed into
|
|
// the functions one by one.
|
|
func Pipeline[T any](funcs ...func(T) T) func(T) T {
|
|
return func(arg T) (result T) {
|
|
result = arg
|
|
for _, fn := range funcs {
|
|
result = fn(result)
|
|
}
|
|
return
|
|
}
|
|
}
|