1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 21:02:27 +08:00
Files
lancet/docs/function.md
2024-09-03 20:25:06 +08:00

9.0 KiB

Function

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

Source:

https://github.com/duke-git/lancet/blob/v1/function/function.go https://github.com/duke-git/lancet/blob/v1/function/watcher.go

Usage:

import (
    "github.com/duke-git/lancet/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 interface{}) func(args ...interface{}) []reflect.Value

Example:

package main

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

func main() {
    arr := []string{"a", "b"}
    f := function.After(len(arr), func(i int) int {
        fmt.Println("last print")
        return i
    })

    type cb func(args ...interface{}) []reflect.Value
    print := func(i int, s string, fn cb) {
        fmt.Printf("arr[%d] is %s \n", i, s)
        fn(i)
    }

    fmt.Println("arr is", arr)
    for i := 0; i < len(arr); i++ {
        print(i, arr[i], f)
    }

    //output:
    // arr is [a b]
    // arr[0] is a
    // arr[1] is b
    // last print
}

Before

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

Signature:

func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value

Example:

package main

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

func main() {
    assert := internal.NewAssert(t, "TestBefore")

    arr := []string{"a", "b", "c", "d", "e"}
    f := function.Before(3, func(i int) int {
        return i
    })

    var res []int64
    type cb func(args ...interface{}) []reflect.Value
    appendStr := func(i int, s string, fn cb) {
        v := fn(i)
        res = append(res, v[0].Int())
    }

    for i := 0; i < len(arr); i++ {
        appendStr(i, arr[i], f)
    }

    expected := []int64{0, 1, 2, 2, 2}
    assert.Equal(expected, res)
}

Curry

Make a curry function.

Signature:

type Fn func(...interface{}) interface{}
func (f Fn) Curry(i interface{}) func(...interface{}) interface{}

Example:

package main

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

func main() {
    add := func(a, b int) int {
        return a + b
    }
    var addCurry function.Fn = func(values ...interface{}) interface{} {
        return add(values[0].(int), values[1].(int))
    }
    add1 := addCurry.Curry(1)
    result := add1(2)
    fmt.Println(result) //3
}

Compose

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

Signature:

func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{}

Example:

package main

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

func main() {
    add1 := func(v ...interface{}) interface{} {
        return v[0].(int) + 1
    }
    add2 := func(v ...interface{}) interface{} {
        return v[0].(int) + 2
    }

    add3 := function.Compose(add1, add2)
    result := add3(1)

    fmt.Println(result) //4
}

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:

package main

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

func main() {
    count := 0
    add := func() {
        count++
    }

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

    time.Sleep(100 * time.Millisecond)
    fmt.Println(count) //1

    function.debouncedAdd()
    time.Sleep(100 * time.Millisecond)
    fmt.Println(count) //2
}

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:

package main

import (
    "fmt"
    "github.com/duke-git/lancet/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
}

Delay

Invoke function after delayed time.

Signature:

func Delay(delay time.Duration, fn interface{}, args ...interface{})

Example:

package main

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

func main() {
    var print = func(s string) {
        fmt.Println(count) //test delay
    }
    function.Delay(2*time.Second, print, "test delay")
}

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:

package main

import (
    "fmt"
    "github.com/duke-git/lancet/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
}

Schedule

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

Signature:

func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool

Example:

package main

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

func main() {
    var res []string
    appendStr := func(s string) {
        res = append(res, s)
    }

    stop := function.Schedule(1*time.Second, appendStr, "*")
    time.Sleep(5 * time.Second)
    close(stop)

    fmt.Println(res) //[* * * * *]
}

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(funcs ...func(interface{}) interface{}) func(interface{}) interface{}

Example:

package main

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

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

    f := 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 (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:

package main

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

func main() {
    w := &function.Watcher{}
    w.Start()

    longRunningTask()

    fmt.Println(w.excuting) //true

    w.Stop()

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

    w.Reset()

    fmt.Println(w.excuting) //false

    fmt.Println(w.startTime) //0
    fmt.Println(w.stopTime) //0
}

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