Fungi provides a great suite of functional stream processing primitives that can be used for a wide range of purposes. Use this library to describe your intent declaratively and produce elegant code that is easy to read and refactor.
go get github.com/sharpvik/fungi@latest
Very soon fungi
will start popping up all over your codebase! And that is a
good thing. Here are some things it can help you with:
Filter
out irrelevant items using a custom validation function.- Apply custom transformations to stream items
(
Map
,TryMap
). - Select a
Range
of items you're interested in. Sort
items with a generic comparator.Page
items efficiently based on page number and size.Loop
through every item (see alsoForEach
).- Collect items into a Go builtin
slice
ormap
(CollectSlice
,CollectMap
). Find
an item that fits a description.
Fungi is very well-tested with a consistent test coverage of over 95%. See for yourself:
git clone [email protected]:sharpvik/fungi.git
cd fungi
go test -cover
[6th of December 2022 checked out at v1.1.0]
PASS
coverage: 98.1% of statements
ok github.com/sharpvik/fungi 0.193s
Moreover, our tests can and should be used as examples: they are written with clarity and readability in mind.
Test files have the
_test.go
suffix. Browse through, don't be shy!
Written with generics, fungi
gives you the flexibility to apply it to any
iterator that implements the very simple fungi.Stream
interface.
Suppose you already have multiple iterable type
s that fetch elements using a
method called Recv
. Here's how you can write a converter function to make them
all comply with the fungi.Stream
interface:
// Every one of your iterable receivers follows this generic interface.
type Receiver[T any] interface {
Recv() (T, error)
}
// receiverStream implements fungi.Stream interface.
type receiverStream[T any] struct {
Receiver[T]
}
// Next wraps Recv method of the origincal Receiver.
func (rs receiverStream[T]) Next() (T, error) {
return rs.Recv()
}
// ReceiverStream converts any Receiver into a fungi.Stream.
func ReceiverStream[T any](r Receiver[T]) fungi.Stream[T] {
return receiverStream[T]{r}
}
Here's how your code is going to look soon:
func GetNamesOfMyDrinkingBuddies() ([]string, error) {
users := ReceiverStream[*User](GetMyFriends())
over18 := fungi.FilterMap(func(u *User) (name string, isLegal bool) {
return u.Name, u.Age >= 18
})
sortAlphabetically := fungi.Sort(func(a, b string) bool { return a < b })
return fungi.CollectSlice(sortAlphabetically(over18(users)))
}