Package fn is a collection of functional golang utilities meant to assist with common slice and map operations, as well as provide some better dexterity around error handling.
go get github.com/sdcoffey/fn
- All
- AllNonZero
- Any
- AnyNonZero
- Chunk
- ChunkWhile
- CompactNil
- CompactZero
- Each
- First
- Flatten
- Map
- Max
- Min
- Must
- Partition
- Reduce
- Reject
- Select
- Seq
- Sum
- Zip
All returns true if all items in the slice satisfy the predicate.
func ExampleAll() {
positiveInts := []int{1, 2, 3}
allPositive := All(positiveInts, func(item int, index int) bool {
return item > 0
})
fmt.Println(allPositive)
// Output: true
}AllNonZero is a helper function that returns true if all items in the slice are not the zero value for their type.
func ExampleAllNonZero() {
nonZeroInts := []string{"one", "two", "three"}
fmt.Println(AllNonZero(nonZeroInts))
zeroInts := []string{"", "", ""}
fmt.Println(AllNonZero(zeroInts))
// Output:
// true
// false
}Any returns true if any item in the slice satisfies the predicate.
func ExampleAny() {
negativeInts := []int{-1, -2, -3}
anyPositive := Any(negativeInts, func(item int, index int) bool {
return item > 0
})
fmt.Println(anyPositive)
// Output: false
}AnyNonZero is a helper function that returns true if any item in the slice is not the zero value for its type.
func ExampleAnyNonZero() {
nonZeroStrings := []string{"one", "", "", "four"}
fmt.Println(AnyNonZero(nonZeroStrings))
zeroStrings := []string{"", ""}
fmt.Println(AnyNonZero(zeroStrings))
// Output:
// true
// false
}Chunk takes []T and returns [][]T, where each subarray has a max length
of chunkSize. If len(items) % chunkSize != 0, the last slice will be
shorter than chunkSize.
func ExampleChunk() {
ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(Chunk(ints, 3))
// Output: [[1 2 3] [4 5 6] [7 8 9]]
}ChunkWhile takes []T and returns [][]T, each of which is a contiguous
chunk of items for which chunker returns true. chunker is called with
the item before and the item after the current item.
func ExampleChunkWhile() {
ints := []int{1, 2, 4, 5, 7}
fmt.Println(ChunkWhile(ints, func(eltBefore, eltAfter int) bool {
return eltBefore+1 == eltAfter
}))
// Output: [[1 2] [4 5] [7]]
}CompactNil returns a new slice with all nil items removed.
func ExampleCompactNil() {
errs := []error{nil, errors.New("example-error 1"), nil, errors.New("example-error 2")}
fmt.Println(CompactNil(errs))
// Output: [example-error 1 example-error 2]
}CompactZero returns a new slice with all zero items removed.
func ExampleCompactZero() {
ints := []int{0, 1, 2, 3, 0, 5}
fmt.Println(CompactZero(ints))
// Output: [1 2 3 5]
}Each calls the given function for each item in the slice.
func ExampleEach() {
Each([]string{"a", "b", "c"}, func(item string, index int) {
fmt.Println(item, index)
})
// Output:
// a 0
// b 1
// c 2
}First will return the first value that satisfies the predicate, and the index at which the value was found (or -1 if it was not found).
func ExampleFirst() {
sequence := []int{-1, 0, 1, 2}
firstPositive, index := First(sequence, func(item int, index int) bool {
return item > 0
})
ten, tenIndex := First(sequence, func(item int, index int) bool {
return item == 10
})
fmt.Printf("value %d at index %d\n", firstPositive, index)
fmt.Printf("value %d at index %d\n", ten, tenIndex)
// Output:
// value 1 at index 2
// value 0 at index -1
}Flatten takes a 2D slice [][]T and flattens it to one dimension,
preserving the original order.
func ExampleFlatten() {
items := [][]string{{"one"}, {"two", "three"}, {"four"}}
fmt.Println(Flatten(items))
// Output: [one two three four]
}Map transforms allows you to transform all values into a slice of other values. The original slice is not modified.
func ExampleMap() {
ints := []int{1, 2, 3}
doubled := Map(ints, func(item int, index int) int {
return item * 2
})
fmt.Println(doubled)
// Output: [2 4 6]
}Max returns the maximum value in some orderable set, or the zero value of the set type if it has len 0.
func ExampleMax() {
fmt.Println(Max(1, 2, 100, -1))
// Output: 100
}Min returns the minimum value in some orderable set, or the zero value of the set type if it has len 0.
func ExampleMin() {
fmt.Println(Min(-100, -300, 3, 100))
// Output: -300
}Must allows you to return one value from a function that would normally return a value and an error. If the error is present, Must will panic.
func ExampleMust() {
canFail := func(shouldFail bool) (string, error) {
if shouldFail {
return "", fmt.Errorf("error")
}
return "success", nil
}
value := Must(canFail(false))
fmt.Println(value)
// Output: success
}Partition takes []T and a predicate function and returns two slices of
T. The first slice contains all the items for which pred returned true,
and the second slice contains all the items for which pred returned false.
func ExamplePartition() {
values := Seq(0, 10, 1)
evens, odds := Partition(values, func(item, index int) bool {
return item%2 == 0
})
fmt.Println(evens)
fmt.Println(odds)
// Output:
// [0 2 4 6 8]
// [1 3 5 7 9]
}Reduce condenses a collection into an accumulated value which is the result
of running each element in the collection though reducer, where each
successive iteration is supplied the return value of the previous.
func ExampleReduce() {
combined := Reduce([]string{"a", "b", "c"}, func(result, item string, index int) string {
return result + item
}, "")
fmt.Println(combined)
// Output: abc
}Reject reduces a slice to only values for which rejector returns false.
func ExampleReject() {
allInts := []int{1, 2, 3, 4, 5, 6}
isEven := func(number int, index int) bool {
return number%2 == 0
}
oddNumbers := Reject(allInts, isEven)
fmt.Println(oddNumbers)
// Output: [1 3 5]
}Select reduces a slice to only values for which selector returns true.
func ExampleSelect() {
allInts := []int{1, 2, 3, 4, 5, 6}
isEven := func(number int, index int) bool {
return number%2 == 0
}
evenNumbers := Select(allInts, isEven)
fmt.Println(evenNumbers)
// Output: [2 4 6]
}Seq Returns a slice of integers from [start, end), incremented by inc.
func ExampleSeq() {
seq := Seq(0, 50, 5)
fmt.Println(seq)
// Output: [0 5 10 15 20 25 30 35 40 45]
}Sum returns the summed value of values in the slice.
func ExampleSum() {
fmt.Println(Sum([]int{1, 2, 3}))
fmt.Println(Sum([]float64{math.Pi, math.Pi}))
// Output:
// 6
// 6.283185307179586
}Zip takes two slices and aggregates them in to a map. If keys and values
are not the same length, Zip will use the shorter of the two to determine
the length of the resulting map
func ExampleZip() {
keys := []string{"one", "two", "three"}
values := []int{1, 2, 3}
fmt.Println(Zip(keys, values))
// Output: map[one:1 three:3 two:2]
}