fuego alternatives and similar packages
Based on the "Functional" category.
Alternatively, view fuego alternatives based on common mentions on social networks and blogs.
-
mo
🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...) -
gofp
A super simple Lodash like utility library with essential functions that empowers the development in Go -
Goterators
A utility library that supports aggregate & transforms functions Go with generic. Such as filter, map, reduce, find, exist -
typact
A zero dependency type action (typact) library for GoLang. [MIRROR] https://gitlab.com/l0nax/typact
CodeRabbit: AI Code Reviews for Developers
Do you think we are missing an alternative of fuego or a related project?
Popular Comparisons
README
Æ’uego - Functional Experiment in Go
Table of content
- Overview
- Documentation
- Installation
- Example Stream
- Contributions
- The Golden rules of the game
- Pressure
- Concept: Entry
- Features summary
- Collectors
- Known limitations
Overview
Making Go come to functional programming.
This is a research project in functional programming which I hope will prove useful!
Æ’uego brings a few functional paradigms to Go. The intent is to save development time while promoting code readability and reduce the risk of complex bugs.
I hope you will find it useful!
Have fun!!
Documentation
The code documentation and some examples can be found on godoc.
The tests form the best source of documentation. Æ’uego comes with a good collection of unit tests and testable Go examples. Don't be shy, open them up and read them and tinker with them!
Note: Most tests use unbuffered channels to help detect deadlocks. In real life scenarios, it is recommended to use buffered channels for increased performance.
Installation
Download
go get github.com/seborama/fuego
Or for a specific version:
go get gopkg.in/seborama/fuego.v8
Import in your code
You can import the package in the usual Go fashion.
To simplify usage, you can use an alias:
package sample
import Æ’ "gopkg.in/seborama/fuego.v8"
...or import as an unqualified dot import:
package sample
import . "gopkg.in/seborama/fuego.v8"
Example Stream
strs := EntrySlice{
EntryString("a"),
EntryString("bb"),
EntryString("cc"),
EntryString("ddd"),
}
NewStreamFromSlice(strs, 500).
Filter(isEntryString).
Distinct().
Collect(
GroupingBy(
stringLength,
Mapping(
stringToUpper,
Filtering(
stringLengthGreaterThan(1),
ToEntrySlice()))))
}
// result: map[1:[] 2:[BB CC] 3:[DDD]]
Contributions
Contributions and feedback are welcome.
For contributions, you must develop in TDD fashion and ideally provide Go testable examples (if meaningful).
If you have an idea to improve Æ’uego, please share it via an issue. And if you like Æ’uego give it a star to show your support for the project - it will put a smile on my face! :blush:
Thanks!!
The Golden rules of the game
Producers close their channel. In other words, when you create a channel, you are responsible for closing it. Similarly, whenever Æ’uego creates a channel, it is responsible for closing it.
Consumers do not close channels.
Producers and consumers should be running in separate Go routines to prevent deadlocks when the channels' buffers fill up.
Pressure
Go channels support buffering that affects the behaviour when combining channels in a pipeline.
When the buffer of a Stream's channel of a consumer is full, the producer will not be able to send more data through to it. This protects downstream operations from overloading.
Presently, a Go channel cannot dynamically change its buffer size. This prevents from adapting the stream flexibly. Constructs that use 'select' on channels on the producer side can offer opportunities for mitigation.
Concept: Entry
Entry
is inspired by hamt.Entry
. This is an elegant solution from Yota Toyama: the type can be anything so long as it respects the simple behaviour of theEntry
interface. This provides an abstraction of types yet with known behaviour:
- Hash(): identifies an Entry Uniquely.
- Equal(): defines equality for a concrete type of
Entry
.Equal()
is expected to be based onHash()
for non-basic types. Equal should ensure the compared Entry is of the same type as the reference Entry. For instance,EntryBool(false)
andEntryInt(0)
both have a Hash of0
, yet they aren't equal.
Several Entry implementations are provided:
- EntryBool
- EntryInt
- EntryFloat
- EntryString
- EntryMap
- EntrySlice
- Tuples
Check the godoc for additional methods each of these may provide.
Features summary
Streams:
- Stream
- IntStream
- FloatStream
- CStream - concurrent implementation of Stream
Functional Types:
- Maybe
- Tuple
- Predicate:
- True
- False
- FunctionPredicate
Functions:
- Consumer
- Function:
- ToIntFunction
- ToFloatFunction
- BiFunction
- StreamFunction:
- FlattenEntrySliceToEntry
- Predicate:
- Or
- Xor
- And
- Not / Negate
Collectors:
- GroupingBy
- Mapping
- FlatMapping
- Filtering
- Reducing
- ToEntrySlice
- ToEntryMap
- ToEntryMapWithKeyMerge
Check the godoc for full details.
Concurrency
As of v8.0.0, a new concurrent model offers to process a stream concurrently while preserving order.
This is not possible yet with all Stream methods but is available with e.g. Stream.Map
.
Notes on concurrency
Concurrent streams are challenging to implement owing to ordering issues in parallel processing. At the moment, the view is that the most sensible approach is to delegate control to users. Multiple Æ’uego streams can be created and data distributed across as desired. This empowers users of Æ’uego to implement the desired behaviour of their pipelines.
Stream
has some methods that fan out (e.g. ForEachC
). See the godoc for further information and limitations.
I recommend Rob Pike's slides on Go concurrency patterns:
As a proof of concept and for facilitation, Æ’uego has a CStream
implementation to manage concurrently a collection of Streams.
Collectors
A Collector
is a mutable reduction operation, optionally transforming the accumulated result.
Collectors can be combined to express complex operations in a concise manner. Simply put, a collector allows creating custom actions on a Stream.
Æ’uego exposes a number of functional methods such as MapToInt
, Head
, LastN
, Filter
, etc...
Collectors also provide a few functional methods.
But... what if you need something else? And it is not straighforward or readable when combining the existing methods Æ’uego offers?
Enters Collector
: implement you own requirement functionally!
Focus on what needs doing in your streams (and delegate the details of the how to the implementation of your Collector
).
Known limitations
- several operations may be memory intensive or poorly performing.