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]
}