Skip to content

Latest commit

 

History

History
785 lines (554 loc) · 15.7 KB

function.md

File metadata and controls

785 lines (554 loc) · 15.7 KB

Function

Package function can control the flow of function execution and support part of functional programming.

Source:

Usage:

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

Index

Documentation

After

Creates a function that invokes given func once it's called n or more times.

Signature:

func After(n int, fn any) func(args ...any) []reflect.Value

Example:Run

package main

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

func main() {
    fn := function.After(2, func() {
        fmt.Println("hello")
    })

    fn()
    fn()

    // Output:
    // hello
}

Before

creates a function that invokes func once it's called less than n times.

Signature:

func Before(n int, fn any) func(args ...any) []reflect.Value

Example:Run

package main

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

func main() {
    fn := function.Before(2, func() {
        fmt.Println("hello")
    })

    fn()
    fn()
    fn()
    fn()

    // Output:
    // hello
    // hello
}

CurryFn

Make curry function.

Signature:

type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T

Example:Run

package main

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

func main() {
    add := func(a, b int) int {
        return a + b
    }

    var addCurry function.CurryFn[int] = func(values ...int) int {
        return add(values[0], values[1])
    }
    add1 := addCurry.New(1)

    result := add1(2)

    fmt.Println(result)

    // Output:
    // 3
}

Compose

Compose the function list from right to left, then return the composed function.

Signature:

func Compose[T any](fnList ...func(...T) T) func(...T) T

Example:Run

package main

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

func main() {
    toUpper := func(strs ...string) string {
        return strings.ToUpper(strs[0])
    }
    toLower := func(strs ...string) string {
        return strings.ToLower(strs[0])
    }
    transform := function.Compose(toUpper, toLower)

    result := transform("aBCde")

    fmt.Println(result)

    // Output:
    // ABCDE
}

Debounce

Creates a debounced version of the provided function. The debounced function will only invoke the original function after the specified delay has passed since the last time it was invoked. It also supports canceling the debounce.

Signature:

func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func())

Example:Run

package main

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

func main() {
    callCount := 0
    fn := func() {
        callCount++
    }

    debouncedFn, _ := function.Debounce(fn, 500*time.Millisecond)

    for i := 0; i < 10; i++ {
        debouncedFn()
        time.Sleep(50 * time.Millisecond)
    }

    time.Sleep(1 * time.Second)
    fmt.Println(callCount)

    debouncedFn()

    time.Sleep(1 * time.Second)
    fmt.Println(callCount)

    // Output:
    // 1
    // 2
}

Debounced

Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.

⚠️ This function is deprecated. use Debounce instead.

Signature:

func Debounced(fn func(), duration time.Duration) func()

Example:Run

package main

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

func main() {
    count := 0

    add := func() {
        count++
    }

    debouncedAdd := function.Debounced(add, 50*time.Microsecond)

    debouncedAdd()
    debouncedAdd()
    debouncedAdd()
    debouncedAdd()

    time.Sleep(100 * time.Millisecond)

    fmt.Println(count)

    debouncedAdd()

    time.Sleep(100 * time.Millisecond)

    fmt.Println(count)

    // Output:
    // 1
    // 2
}

Delay

Invoke function after delayed time.

Signature:

func Delay(delay time.Duration, fn any, args ...any)

Example:Run

package main

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

func main() {
    var print = func(s string) {
        fmt.Println(s)
    }

    function.Delay(2*time.Second, print, "hello")

    // Output:
    // hello
}

Schedule

Invoke function every duration time, until close the returned bool chan.

Signature:

func Schedule(d time.Duration, fn any, args ...any) chan bool

Example:Run

package main

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

func main() {
    count := 0

    increase := func() {
        count++
    }

    stop := function.Schedule(2*time.Second, increase)

    time.Sleep(2 * time.Second)
    close(stop)

    fmt.Println(count)

    // Output:
    // 2
}

Pipeline

Pipeline takes a list of functions and returns a function whose param will be passed into the functions one by one.

Signature:

func Pipeline[T any](funcs ...func(T) T) func(T) T

Example:Run

package main

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

func main() {
    addOne := func(x int) int {
        return x + 1
    }
    double := func(x int) int {
        return 2 * x
    }
    square := func(x int) int {
        return x * x
    }

    fn := function.Pipeline(addOne, double, square)

    result := fn(2)

    fmt.Println(result)

    // Output:
    // 36
}

Watcher

Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.

Signature:

type Watcher struct {
    startTime int64
    stopTime  int64
    excuting  bool
}
func NewWatcher() *Watcher
func (w *Watcher) Start() //start the watcher
func (w *Watcher) Stop() //stop the watcher
func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution

Example:Run

package main

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

func main() {
    w := function.NewWatcher()

    w.Start()

    longRunningTask()

    fmt.Println(w.excuting) //true

    w.Stop()

    eapsedTime := w.GetElapsedTime().Milliseconds()

    fmt.Println(eapsedTime)

    w.Reset()
}

func longRunningTask() {
    var slice []int64
    for i := 0; i < 10000000; i++ {
        slice = append(slice, int64(i))
    }
}

And

Returns a composed predicate that represents the logical AND of a list of predicates. It evaluates to true only if all predicates evaluate to true for the given value.

Signature:

func And[T any](predicates ...func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    isNumericAndLength5 := function.And(
        func(s string) bool { return strings.ContainsAny(s, "0123456789") },
        func(s string) bool { return len(s) == 5 },
    )

    fmt.Println(isNumericAndLength5("12345"))
    fmt.Println(isNumericAndLength5("1234"))
    fmt.Println(isNumericAndLength5("abcde"))

    // Output:
    // true
    // false
    // false
}

Or

Returns a composed predicate that represents the logical OR of a list of predicates. It evaluates to true if at least one of the predicates evaluates to true for the given value.

Signature:

func Or[T any](predicates ...func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    containsDigitOrSpecialChar := function.Or(
        func(s string) bool { return strings.ContainsAny(s, "0123456789") },
        func(s string) bool { return strings.ContainsAny(s, "!@#$%") },
    )

    fmt.Println(containsDigitOrSpecialChar("hello!"))
    fmt.Println(containsDigitOrSpecialChar("hello"))

    // Output:
    // true
    // false
}

Negate

Returns a predicate that represents the logical negation of this predicate.

Signature:

func Negate[T any](predicate func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    // Define some simple predicates for demonstration
    isUpperCase := func(s string) bool {
        return strings.ToUpper(s) == s
    }
    isLowerCase := func(s string) bool {
        return strings.ToLower(s) == s
    }
    isMixedCase := function.Negate(function.Or(isUpperCase, isLowerCase))

    fmt.Println(isMixedCase("ABC"))
    fmt.Println(isMixedCase("AbC"))

    // Output:
    // false
    // true
}

Nor

Returns a composed predicate that represents the logical NOR of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.

Signature:

func Nor[T any](predicates ...func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    match := function.Nor(
        func(s string) bool { return strings.ContainsAny(s, "0123456789") },
        func(s string) bool { return len(s) == 5 },
    )

    fmt.Println(match("dbcdckkeee"))


    match = function.Nor(
        func(s string) bool { return strings.ContainsAny(s, "0123456789") },
        func(s string) bool { return len(s) == 5 },
    )

    fmt.Println(match("0123456789"))

    // Output:
    // true
    // false
}

Nand

Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.

Signature:

func Nand[T any](predicates ...func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    isNumericAndLength5 := function.Nand(
        func(s string) bool { return strings.ContainsAny(s, "0123456789") },
        func(s string) bool { return len(s) == 5 },
    )

    fmt.Println(isNumericAndLength5("12345"))
    fmt.Println(isNumericAndLength5("1234"))
    fmt.Println(isNumericAndLength5("abcdef"))

    // Output:
    // false
    // false
    // true
}

Xnor

Returns a composed predicate that represents the logical XNOR of a list of predicates. It evaluates to true only if all predicates evaluate to true or false for the given value.

Signature:

func Xnor[T any](predicates ...func(T) bool) func(T) bool

Example:Run

package main

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

func main() {
    isEven := func(i int) bool { return i%2 == 0 }
    isPositive := func(i int) bool { return i > 0 }

    match := function.Xnor(isEven, isPositive)

    fmt.Println(match(2))
    fmt.Println(match(-3))
    fmt.Println(match(3))

    // Output:
    // true
    // true
    // false
}

AcceptIf

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.

Signature:

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

Example:Run

package main

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

func main() {

    adder := function.AcceptIf(
        function.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
}

Throttle

Throttle creates a throttled version of the provided function. The returned function guarantees that it will only be invoked at most once per interval.

Signature:

func Throttle(fn func(), interval time.Duration) func()

Example:Run

package main

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

func main() {
    callCount := 0

    fn := func() {
        callCount++
    }

    throttledFn := function.Throttle(fn, 1*time.Second)

    for i := 0; i < 5; i++ {
        throttledFn()
    }

    time.Sleep(1 * time.Second)

    fmt.Println(callCount)

    // Output:
    // 1
}