Skip to content

streamz/ginsu

Repository files navigation

ginsu

CircleCI GoDoc

The ginsu library provides higher order functions mainly for slices.

Unfortunately golang does not support generics :(

Any type of slice can be wrapped in type T

Unfortunately higher order functions require the use of reflection, so they are not recommended for performance sensitve code.

supported higer order functions:

Apply(fn F, args ...T) (func()T, error)

AsyncRepeat(fn F, defered func()) func()

Compare(t0, t1 T, fn F) (bool, error)

Filter(t T, fn F) (T, error)

FilterNot(t T, fn F) (T, error)

ForAll(t T, fn F) (bool, error)

ForAny(t T, fn F) (bool, error)

ForEach(t T, fn F)

Map(t T, fn F) (T, error)

Reduce(initial, t T, fn F) (T, error)

Usage:

    // simple hof(s)

    // Apply
    fn, _ := Apply(F{func(a, b int) int {
	return a + b
    }}, T{1}, T{1})
    
    // res == 2
    res := fn().I.(int)

    // AsyncRepeat
    stop := AsyncRepeat(F{func() {
	// do something
    }}, func() {
        // do something defered
    })
    
    // stop doing something
    stop()


    // slice hof(s)

    type point struct {
        x, y int
    }
    
    type line struct {
        x, y point
    }
    
    td := struct {
        in, expect []point
    }{
        []point{{1, 1}, {2, 2}, {3, 3},{4, 4}},
        []point{{1, 1}, {2, 2}, {3, 3},{4, 4}},
    }
    

    // Compare
    ok, err := Compare(T{td.in}, T{td.expect}, F{func(p0, p1 point) bool {
        return p0 == p1
    }})


    // Filter
    res, err := Filter(T{td.in}, F{func(p point) bool {
        return (p.x % 2 == 0)
    }})

    result := res.I.([]point)


    // FilterNot
    res, _ := FilterNot(T{td.in}, F{func(p point) bool {
        return (p.x % 2 == 0)
    }})
    
    result := res.I.([]point)
    

    // ForAll
    ok, err := ForAll(T{td}, F{func(p point) bool {
        return (p.x == p.y)
    }})
  
  
    // ForAny
    ok, err := ForAny(T{td}, F{func(p point) bool {
        return (p == point{2, 2})
    }})
  

    // ForEach
    res := make([]point, len(td.expect))
    idx := 0
    ForEach(T{td.in}, F{func(p point) {
        res[idx] = point{p.x*2, p.y*2}
        idx++
    }})
  
    result := res.I.([]point)


    // Map
    res, _ := Map(T{in}, F{func(p point) line {
        return line{p, point{p.x*10, p.y*10}}
    }})
    
    result := res.I.([]line)


    // Reduce
    res, _ := Reduce(T{point{0,0}}, T{td}, F{func(acc, p point) point {
        return point{acc.x + p.x, acc.y + p.y}
    }})
    
    result := res.I.(point)