Stadio
Compendium of functions, data structures, monadic wrappers and more which, hopefully, will be
included as a standard library of the language
Modules
Slices
Package slices provides utilities to work with slices
Table of contents
Cut
Cut removes a sector from slice given lower and upper bounds. Bounds are
represented as indices of the slice. E.g:
Cut([1, 2, 3, 4], 1, 2) -> [1, 4]
Cut([4], 0, 0) -> []
Cut will returned the original slice without the cut subslice.
Code
func Cut[T any](arr []T, from, to int) []T {
if len(arr) < 1 {
return arr
}
if from < 0 {
from = 0
}
if from >= len(arr) {
from = len(arr) - 1
}
if to < 0 {
to = 0
}
if to >= len(arr) {
to = len(arr) - 1
}
if len(arr) == 1 {
return arr[:0]
}
if from > to {
return append(arr[:from], arr[from+to+1:]...)
}
return append(arr[:from], arr[to+1:]...)
}
Delete
Delete removes the element in idx
position, without preserving array order. In case idx
is out of bounds, noop.
Code
func Delete[T any](arr []T, idx int) []T {
le := len(arr) - 1
if le < 0 || idx > le || idx < 0 {
return arr
}
var t T
arr[idx] = arr[le]
arr[le] = t
arr = arr[:le]
return arr
}
DeleteOrder
DeleteOrder removes the element in idx
position, preserving array order. In case idx
is out of bounds, noop.
Code
func DeleteOrder[T any](arr []T, idx int) []T {
le := len(arr) - 1
if le < 0 || idx > le || idx < 0 {
return arr
}
var t T
if le > 0 {
copy(arr[idx:], arr[idx+1:])
}
arr[le] = t
arr = arr[:le]
return arr
}
Extract gets and deletes the element than matches predicate. Returned values are the
modified slice, the item or zero value if not found, and whether item was found
Code
func Extract[T any](arr []T, predicate func(t T) bool) ([]T, T, bool) {
res, idx := FindIdx(arr, predicate)
if idx < 0 {
return arr, res, false
}
arr = Delete(arr, idx)
return arr, res, true
}
ExtractIdx gets and deletes the element at the given position. Returned values are the
modified slice, the item or zero value if not found, and whether item was found
Code
func ExtractIdx[T any](arr []T, idx int) (res []T, item T, ok bool) {
if idx >= len(arr) || idx < 0 {
return
}
ok = true
item = arr[idx]
res = Delete(arr, idx)
return
}
Find
Find returns the first element that matches predicate
Code
func Find[T any](arr []T, predicate func(t T) bool) (res T, ok bool) {
var idx int
res, idx = FindIdx(arr, predicate)
ok = idx > -1
return
}
FindIdx
FindIdx returns the first element that matches predicate as well as the position on the slice.
Code
func FindIdx[T any](arr []T, predicate func(t T) bool) (res T, idx int) {
idx = IndexOf(arr, predicate)
if idx < 0 {
return
}
res = arr[idx]
return
}
Insert
Insert places the given item at the position idx
for the given slice
Code
func Insert[T any](arr []T, item T, idx int) []T {
if arr == nil {
return []T{item}
}
if idx < 0 || idx > len(arr) {
return arr
}
return append(arr[:idx], append([]T{item}, arr[idx:]...)...)
}
InsertVector
InsertVector places the given vector at the position idx
for the given slice, moving
existing elements to the right.
Code
func InsertVector[T any](arr, items []T, idx int) (res []T) {
if arr == nil {
res = items[:]
return
}
if items == nil || len(items) == 0 {
res = arr
return
}
if idx < 0 || idx > len(arr) {
return arr
}
return append(arr[:idx], append(items, arr[idx:]...)...)
}
Peek
Peek returns the item corresponding to idx
Code
func Peek[T any](arr []T, idx int) (item T, ok bool) {
if len(arr) < 1 || idx >= len(arr) {
return
}
item = arr[idx]
ok = true
return
}
Pop
Pop deletes and returns the last item from the slice, starting from the end.
Code
func Pop[T any](arr []T) (res []T, item T, ok bool) {
if len(arr) < 1 {
return
}
var t T
le := len(arr) - 1
res = arr[:le]
item = arr[le]
ok = true
arr[le] = t
return
}
PopFront
PopFront retrieves and deletes the element at the head of the slice
Code
func PopFront[T any](arr []T) (res []T, item T, ok bool) {
if len(arr) < 1 {
res = arr
return
}
item, res = arr[0], arr[1:]
return
}
PushFront
PushFront inserts the item at the head of the slice
Code
func PushFront[T any](arr []T, item T) []T {
return append([]T{item}, arr...)
}
Shift
Shift inserts the item at the head of the slice
Code
func Shift[T any](arr []T) ([]T, T, bool) {
return PopFront(arr)
}
Unshift
Unshift inserts the item at the head of the slice
Code
func Unshift[T any](arr []T, item T) []T {
return PushFront(arr, item)
}
Maps
Package maps provides utilities to work with maps
Table of contents
Equals
Equals returns whether 2 maps are equals in values
Code
func Equals[K comparable, V any](m1, m2 map[K]V, eq func(V, V) bool) bool {
if len(m1) != len(m2) {
return false
}
if m1 == nil && m2 != nil {
return false
}
if m1 != nil && m2 == nil {
return false
}
for k1, v1 := range m1 {
v2, ok := m2[k1]
if !ok {
return false
}
if !eq(v1, v2) {
return false
}
}
return true
}
Filter
Filter discards those entries from the map that do not match predicate.
Code
func Filter[K comparable, V any](
m map[K]V,
p func(K, V) bool,
) map[K]V {
if m == nil {
return nil
}
res := make(map[K]V, len(m))
for k, v := range m {
if p(k, v) {
res[k] = v
}
}
return res
}
FilterInPlace
FilterInPlace deletes those entries from the map that do not match predicate.
Code
func FilterInPlace[K comparable, V any](
m map[K]V,
p func(K, V) bool,
) map[K]V {
if m == nil {
return nil
}
for k, v := range m {
if !p(k, v) {
delete(m, k)
}
}
return m
}
FilterMap
FilterMap both filters and maps a map. The predicate function should return a fp.Option monad:
fp.Some to indicate the entry should be kept.
fp.None to indicate the entry should be discarded
Code
func FilterMap[K1 comparable, V1 any, K2 comparable, V2 any](
m map[K1]V1,
p func(K1, V1) fp.Option[tuples.Tuple2[K2, V2]],
) map[K2]V2 {
if m == nil {
return nil
}
res := make(map[K2]V2, len(m))
for k1, v1 := range m {
tpl := p(k1, v1)
if tpl.IsSome() {
v := tpl.UnwrapUnsafe()
res[v.V1] = v.V2
}
}
return res
}
FilterMapTuple
FilterMapTuple both filters and maps the given map by receiving a predicate
which returns mapped values, and a boolean to indicate whether that entry
should be kept.
Code
func FilterMapTuple[K1 comparable, V1 any, K2 comparable, V2 any](
m map[K1]V1,
p func(K1, V1) (K2, V2, bool),
) map[K2]V2 {
if m == nil {
return nil
}
res := make(map[K2]V2, len(m))
for k1, v1 := range m {
if k2, v2, ok := p(k1, v1); ok {
res[k2] = v2
}
}
return res
}
Fold
Fold compacts the given map into a single type by taking into account the initial value
Code
func Fold[K comparable, V any, R any](
m map[K]V,
p func(R, K, V) R,
initial R,
) R {
if m == nil {
return initial
}
r := initial
for k, v := range m {
r = p(r, k, v)
}
return r
}
Map
Map transforms a map into another one, with same or different types
Code
func Map[K1 comparable, V1 any, K2 comparable, V2 any](
m map[K1]V1,
p func(K1, V1) (K2, V2),
) map[K2]V2 {
if m == nil {
return nil
}
res := make(map[K2]V2, len(m))
for k1, v1 := range m {
k2, v2 := p(k1, v1)
res[k2] = v2
}
return res
}
Reduce
Reduce compacts the given map into a single type
Code
func Reduce[K comparable, V any, R any](
m map[K]V,
p func(R, K, V) R,
) R {
var r R
if m == nil {
return r
}
for k, v := range m {
r = p(r, k, v)
}
return r
}
Slice
Slice converts a map into a slice
Code
func Slice[K comparable, V, R any](
m map[K]V,
p func(K, V) R,
) slices.Slice[R] {
res := make([]R, len(m))
i := 0
for k, v := range m {
res[i] = p(k, v)
i++
}
return res
}
Fp
Table of contents
Fp
Table of contents