Documentation
¶
Overview ¶
Package fun is a zero-dependency collection of tools and idoms that takes advantage of generics. Iterators, error handling, a native-feeling Set type, and a simple pub-sub framework for distributing messages in fan-out patterns.
Index ¶
- Variables
- func Check(fn func()) (err error)
- func Ignore[T any](fn func(T) error, arg T)
- func IgnoreMust[T any, O any](fn func(T) (O, error), arg T) O
- func Invariant(cond bool, args ...any)
- func InvariantCheck(fn func() error, args ...any)
- func InvariantMust(err error, args ...any)
- func Is[T any](in any) bool
- func IsInvariantViolation(r any) bool
- func IsWrapped[T any](in T) bool
- func IsZero[T comparable](in T) bool
- func IterateOne[T any](ctx context.Context, iter Iterator[T]) (T, error)
- func Must[T any](arg T, err error) T
- func Observe[T any](ctx context.Context, iter Iterator[T], fn Observer[T]) (err error)
- func Protect[I any, O any](fn func(I) (O, error)) func(I) (O, error)
- func ReadOne[T any](ctx context.Context, ch <-chan T) (T, error)
- func Safe[T any](fn func() T) (out T, err error)
- func Unwind[T any](in T) []T
- func Unwrap[T any](in T) T
- func WhenCall(cond bool, op func())
- func WhenDo[T any](cond bool, op func() T) T
- func Zero[T any](T) T
- func ZeroOf[T any]() T
- func ZeroWhenNil[T any](val any) T
- type Iterator
- type Observer
- type Pair
- type Pairs
- type Send
- type WaitFunc
- func WaitBlocking(fn func()) WaitFunc
- func WaitBlockingObserve[T any](observe func(T), wait func() T) WaitFunc
- func WaitChannel[T any](ch <-chan T) WaitFunc
- func WaitContext(ctx context.Context) WaitFunc
- func WaitForGroup(wg *sync.WaitGroup) WaitFunc
- func WaitMerge(ctx context.Context, iter Iterator[WaitFunc]) WaitFunc
- func WaitObserve[T any](observe func(T), ch <-chan T) WaitFunc
- func WaitObserveAll[T any](observe func(T), ch <-chan T) WaitFunc
- func WaitObserveAllCtx[T any](observe func(context.Context, T), ch <-chan T) WaitFunc
- func (wf WaitFunc) Add(ctx context.Context, wg *WaitGroup)
- func (wf WaitFunc) Block()
- func (wf WaitFunc) BlockSignal() <-chan struct{}
- func (wf WaitFunc) CheckWorker() WorkerFunc
- func (wf WaitFunc) Run(ctx context.Context)
- func (wf WaitFunc) Signal(ctx context.Context) <-chan struct{}
- func (wf WaitFunc) WithTimeout(timeout time.Duration)
- func (wf WaitFunc) WithTimeoutSignal(timeout time.Duration) <-chan struct{}
- func (wf WaitFunc) Worker() WorkerFunc
- type WaitGroup
- type WorkerFunc
- func (wf WorkerFunc) Block() error
- func (wf WorkerFunc) MustWait() WaitFunc
- func (wf WorkerFunc) Observe(ctx context.Context, ob Observer[error])
- func (wf WorkerFunc) ObserveWait(ob Observer[error]) WaitFunc
- func (wf WorkerFunc) Run(ctx context.Context) error
- func (wf WorkerFunc) Safe(ctx context.Context) (err error)
- func (wf WorkerFunc) Singal(ctx context.Context) <-chan error
- func (wf WorkerFunc) WithTimeout(timeout time.Duration) error
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvariantViolation is the root error of the error object that is // the content of all panics produced by the Invariant helper. ErrInvariantViolation = errors.New("invariant violation") // ErrRecoveredPanic is at the root of any error returned by a // function in the fun package that recovers from a panic. ErrRecoveredPanic = errors.New("recovered panic") )
var ErrSkippedBlockingSend = errors.New("skipped blocking send")
ErrSkippedBlockingSend is returned when sending into a channel, in a non-blocking context, when the channel was blocking and the send was therefore skipped.
Functions ¶
func Check ¶ added in v0.3.0
func Check(fn func()) (err error)
Check, like Safe, runs a function without arguments that does not produce an error, and, if the function panics, converts it into an error.
func Ignore ¶ added in v0.8.3
Ignore runs a function that takes an arbitrary argument and ignores the error and swallows any panic. This is a risky move: usually functions panic for a reason, but for certain invariants this may be useful.
Be aware, that while Ignore will recover from any panics, defers within the ignored function will not run unless there is a call to recover *before* the defer.
func IgnoreMust ¶ added in v0.8.3
IgnoreMust runs a function that takes an arbitrary argument and ignores the error and swallows any panic, returning the output of the function, likely a Zero value, in the case of an error. This is a risky move: usually functions panic for a reason, but for certain invariants this may be useful.
Be aware, that while Ignore will recover from any panics, defers within the ignored function will not run unless there is a call to recover *before* the defer.
func Invariant ¶ added in v0.3.0
Invariant panics if the condition is false Invariant panics, passing an error that is rooted by ErrInvariantViolation.
func InvariantCheck ¶ added in v0.6.0
InvariantCheck calls the function and if it returns an error panics with an ErrInvariantViolation error, wrapped with the error of the function, and any annotation arguments.
func InvariantMust ¶ added in v0.6.0
InvariantMust raises an invariant error if the error is not nil. The content of the panic is both--via wrapping--an ErrInvariantViolation and the error itself.
func Is ¶
Is a generic version of `errors.Is` that takes advantage of the Unwrap function, and is useful for checking if an object of an interface type is or wraps an implementation of the type parameter.
func IsInvariantViolation ¶ added in v0.3.0
IsInvariantViolation returns true if the argument is or resolves to ErrInvariantViolation.
func IsWrapped ¶ added in v0.8.0
IsWrapped returns true if the input value wraps another value of the same type.
func IsZero ¶ added in v0.8.0
func IsZero[T comparable](in T) bool
IsZero returns true if the input value compares "true" to the zero value for the type of the argument. If the type implements an IsZero() method (e.g. time.Time), then IsZero returns that value, otherwise, IsZero constructs a zero valued object of type T and compares the input value to the zero value.
func IterateOne ¶ added in v0.8.5
IterateOne, like ReadOne reads one value from the iterator, and returns it. The error values are either a context cancelation error if the context is canceled, or io.EOF if there are no elements in the iterator.
IterateOne does not provide atomic exclusion if multiple calls to the iterator or IterateOne happen concurrently; however, the adt.NewIterator wrapper provides a special case which *does* allow for concurrent use.
func Must ¶
Must wraps a function that returns a value and an error, and converts the error to a panic.
func Observe ¶ added in v0.7.0
Observe processes an iterator calling the observer function for every element in the iterator and retruning when the iterator is exhausted. Take care to ensure that the Observe function does not block.
Use itertool.Observe and itertool.ParallelObserve for more advanced execution patterns.
Use with itertool.Slice, itertool.Channel, or itertool.Variadic to process data in other forms.
func Protect ¶ added in v0.8.5
Protect wraps a function with a panic handler, that will parse and attach the content of the pantic to the error output (while maintaining the functions orginial error.) All handled panics will be annotated with fun.ErrRecoveredPanic.
func ReadOne ¶ added in v0.7.0
ReadOnce reads one item from the channel, and returns it. ReadOne returns early if the context is canceled (ctx.Err()) or the channel is closed (io.EOF).
func Unwind ¶ added in v0.8.0
func Unwind[T any](in T) []T
Unwind uses the Unwrap operation to build a list of the "wrapped" objects.
func Unwrap ¶
func Unwrap[T any](in T) T
Unwrap is a generic equivalent of the `errors.Unwrap()` function for any type that implements an `Unwrap() T` method. useful in combination with Is.
func WhenCall ¶ added in v0.8.5
func WhenCall(cond bool, op func())
WhenCall runs a function when condition is true, and is a noop otherwise.
func WhenDo ¶ added in v0.8.5
WhenDo calls the function when the condition is true, and returns the result, or if the condition is false, the operation is a noop, and returns zero-value for the type.
func Zero ¶ added in v0.8.0
func Zero[T any](T) T
Zero returns the zero-value for the type T of the input argument.
func ZeroOf ¶ added in v0.8.0
func ZeroOf[T any]() T
ZeroOf returns the zero-value for the type T specified as an argument.
func ZeroWhenNil ¶ added in v0.8.0
ZeroWhenNil takes a value of any type, and if that value is nil, returns the zero value of the specified type. Otherwise, ZeroWhenNil coerces the value into T and returns it. If the input value does not match the output type of the function, ZeroWhenNil panics with an ErrInvariantViolation.
Types ¶
type Iterator ¶
Iterator provides a safe, context-respecting iterator paradigm for iterable objects, along with a set of consumer functions and basic implementations.
The itertool package provides a number of tools and paradigms for creating and processing Iterator objects, including Generators, Map and Reduce, Filter as well as Split and Merge to combine or divide iterators.
In general, Iterators cannot be safe for access from multiple concurrent goroutines, because it is impossible to synchronize calls to Next() and Value(); however, itertool.Range() and itertool.Split() provide support for these workloads.
func Generator ¶ added in v0.8.5
Generator creates an iterator that produces new values, using the generator function provided. This implementation does not create any background go routines, and the iterator will produce values until the function returns an error or the Close() method is called. Any non-nil error returned by the generator function is propagated to the close method, as long as it is not a context cancellation error or an io.EOF error.
type Observer ¶ added in v0.8.5
type Observer[T any] func(T)
Observer describes a function that operates on a single object, but returns no output, and is used primarly for side effects, particularly around handling errors or collecting metrics. The Observer implementation here makes it possible to provide panic-safety for these kinds of functions or easily convert to other related types.
func (Observer[T]) Safe ¶ added in v0.8.5
Safe handles any panic encountered during the observer's execution and converts it to an error.
func (Observer[T]) Wait ¶ added in v0.8.5
Wait captures a variable and converts an Observer into a wait function that observes the value when the WaitFunc runs.
func (Observer[T]) Worker ¶ added in v0.8.5
func (of Observer[T]) Worker(in T) WorkerFunc
Worker captures a variable and returns a worker function which will, when executed, observe the input value. These worker functions, use the Safe-mode of execution.
type Pair ¶ added in v0.8.5
type Pair[K comparable, V any] struct { Key K Value V }
Pair represents a key-value pair. Used by the adt synchronized map implementation and the set package to handle ordered key-value pairs.
func MakePair ¶ added in v0.8.5
func MakePair[K comparable, V any](k K, v V) Pair[K, V]
MakePair constructs a pair object. This is identical to using the literal constructor but may be more ergonomic.
type Pairs ¶ added in v0.8.5
type Pairs[K comparable, V any] []Pair[K, V]
Pairs implements a collection of key-value pairs.
func MakePairs ¶ added in v0.8.5
func MakePairs[K comparable, V any](in map[K]V) Pairs[K, V]
MakePairs converts a map type into a slice of Pair types that can be usable in a set.
func (*Pairs[K, V]) Add ¶ added in v0.8.5
func (p *Pairs[K, V]) Add(k K, v V)
Add adds a new value to the underlying slice. This may add a duplicate key.
func (Pairs[K, V]) Append ¶ added in v0.8.5
Append, mirroring the semantics of the built in append() function adds one or more Pair items to a Pairs slice, and returns the new slice without changing the value of the original slice:
p = p.Append(pair, pare, pear)
func (Pairs[K, V]) Map ¶ added in v0.8.5
func (p Pairs[K, V]) Map() map[K]V
Map converts a list of pairs to the equivalent map. If there are duplicate keys in the Pairs list, only the first occurrence of the key is retained.
func (Pairs[K, V]) MarshalJSON ¶ added in v0.8.5
MarshalJSON produces a JSON encoding for the Pairs object by first converting it to a map and then encoding that map as JSON. The JSON serialization does not necessarily preserve the order of the pairs object.
func (*Pairs[K, V]) UnmarshalJSON ¶ added in v0.8.5
UnmarshalJSON provides consistent JSON decoding for Pairs objects. It reads a JSON document into a map and converts it to pairs, and appends it to the existing Pairs objects without removing or resetting the current object.
type Send ¶ added in v0.8.5
type Send[T any] struct { // contains filtered or unexported fields }
Send provides a functional and descriptive interface for sending into channels. The only meaningful use of Send objects is via the Blocking() and NonBlocking() constructors. Invocations resemble:
ch := make(chan int) err := fun.Blocking(ch).Send(ctx, 42) // handle error, which is always a context cancellation error
There are three kinds of sends: Check, which returns a boolean if the send was successful; Send(), which returns the error useful if you need to distinguish between timeouts and cancellations; and Ignore which has no response.
Send operations against closed channels return io.EOF (or false, in the case of Check) rather than panicing.
func Blocking ¶ added in v0.8.5
Blocking produces a blocking Send instance. All Send/Check/Ignore operations will block until the context is canceled, the channel is canceled, or the send succeeds.
func NonBlocking ¶ added in v0.8.5
NonBlocking produces a send instance that performs a non-blocking send.
func (Send[T]) Check ¶ added in v0.8.5
Check performs a send and returns true when the send was successful.
type WaitFunc ¶ added in v0.6.3
WaitFunc is a type of function object that will block until an operation returns or the context is canceled.
func WaitBlocking ¶ added in v0.6.5
func WaitBlocking(fn func()) WaitFunc
WaitBlocking is a convenience function to use simple blocking functions into WaitFunc objects. Because these WaitFunc functions do not resepct the WaitFunc context, use with care and caution.
func WaitBlockingObserve ¶ added in v0.6.5
WaitBlockingObserve is a convenience function that creates a WaitFunc that wraps a simple function that returns a single value, and observes that output with the observer function.
Because these WaitFunc functions do not resepct the WaitFunc context, use with care and caution.
func WaitChannel ¶ added in v0.6.3
WaitChannel converts a channel (typically, a `chan struct{}`) to a WaitFunc. The WaitFunc blocks till it's context is canceled or the channel is either closed or returns one item.
func WaitContext ¶ added in v0.6.3
WaitContext wait's for the context to be canceled before returning. The WaitFunc that's return also respects it's own context. Use this WaitFunc and it's own context to wait for a context to be cacneled with a timeout, for instance.
func WaitForGroup ¶ added in v0.8.0
WaitForGroup converts a sync.WaitGroup into a fun.WaitFunc.
This operation will leak a go routine if the WaitGroup never returns and the context is canceled. To avoid a leaked goroutine, use the fun.WaitGroup type.
func WaitMerge ¶ added in v0.6.3
WaitMerge starts a goroutine that blocks on each WaitFunc provided and returns a WaitFunc that waits for all of these goroutines to return. The constituent WaitFunc are passed WaitMerge's context, while the returned WaitFunc respects its own context.
Use itertool.Variadic, itertool.Slice, or itertool.Channel to convert common container types/calling patterns to an iterator.
In combination with erc.CheckWait, you can use WaitMerge to create and pubsub.Queue or pubsub.Deque blocking iterators to create worker pools.
func WaitObserve ¶ added in v0.6.3
WaitObserve passes the output of the channel into the observer function and then returns. If the context is canceled the output of the channel is not observed.
WaitObserve consumes and observes, at most, one item from the channel. Callers must call the WaitFunc.
func WaitObserveAll ¶ added in v0.6.3
WaitObserveAll passes the output of the channel into the observer function, waiting for the input channel to be closed or the WaitFunc's context to be canceled. WaitObserveAll does not begin processing the channel until the WaitFunc is called.
func WaitObserveAllCtx ¶ added in v0.8.0
WaitObserveAllCtx passes the output of the channel into the observer function with a context, waiting for the input channel to be closed or the WaitFunc's context to be canceled. WaitObserveAll does not begin processing the channel until the WaitFunc is called.
func (WaitFunc) Add ¶ added in v0.8.0
Add starts a goroutine that waits for the WaitFunc to return, incrementing and decrementing the sync.WaitGroup as appropriate. The execution of the wait fun blocks on Add's context.
func (WaitFunc) Block ¶ added in v0.6.3
func (wf WaitFunc) Block()
Block runs the WaitFunc with a context that will never be canceled.
func (WaitFunc) BlockSignal ¶ added in v0.8.0
func (wf WaitFunc) BlockSignal() <-chan struct{}
BlockSignal runs the WaitFunc in a background goroutine and returns a signal channel that is closed when the operation completes. As in Block() the WaitFunc is passed a background context that is never canceled.
Callers are responsble for handling the (potential) panic in the WaitFunc.
func (WaitFunc) CheckWorker ¶ added in v0.8.0
func (wf WaitFunc) CheckWorker() WorkerFunc
CheckWorker converts a wait function into a WorkerFunc, running the wait function inside of a Check() function, which catches panics and turns them into the worker function's errors.
func (WaitFunc) Run ¶ added in v0.8.0
Run is equivalent to calling the wait function directly, except the context passed to the function is always canceled when the wait function returns.
func (WaitFunc) Signal ¶ added in v0.8.0
Signal runs the WaitFunc in a goroutine and returns a signal channel that is canceled when the function completes. Useful for bridging the gap between interfaces and integration that use channels and functions.
Callers are responsble for handling the (potential) panic in the WaitFunc.
func (WaitFunc) WithTimeout ¶ added in v0.6.6
WithTimeout runs the WaitFunc with an explicit timeout.
func (WaitFunc) WithTimeoutSignal ¶ added in v0.8.0
WithTimeoutSignal executes the WaitFunc as in WithTimeout, but returns a singal channel that is closed when the task completes.
Callers are responsble for handling the (potential) panic in the WaitFunc.
func (WaitFunc) Worker ¶ added in v0.8.0
func (wf WaitFunc) Worker() WorkerFunc
Worker converts a wait function into a WorkerFunc. These workers will never error.
type WaitGroup ¶ added in v0.6.3
type WaitGroup struct {
// contains filtered or unexported fields
}
WaitGroup works like sync.WaitGroup, except that the Wait method takes a context (and can be passed as a fun.WaitFunc). The implementation is exceptionally simple. The only constraint, like sync.WaitGroup, is that you can never modify the value of the internal counter such that it is negative, event transiently. The implementation does not require background resources aside from Wait, which creates a single goroutine that lives for the entire time that Wait is running, but no other background resources are created. Multiple copies of Wait can be safely called at once, and the WaitGroup is reusable more than once.
This implementation is about 50% slower than sync.WaitGroup after informal testing. It provides a little extra flexiblity and introspection, with similar semantics, that may be worth the additional performance hit.
func (*WaitGroup) Add ¶ added in v0.8.0
Add modifies the internal counter. Raises an ErrInvariantViolation error if any modification causes the internal coutner to be less than 0.
func (*WaitGroup) Done ¶ added in v0.8.0
func (wg *WaitGroup) Done()
Done marks a single operation as done.
func (*WaitGroup) IsDone ¶ added in v0.8.0
IsDone returns true if there is pending work, and false otherwise.
type WorkerFunc ¶ added in v0.8.0
WorkerFunc represents a basic function used in worker pools and other similar situations
func ObserveWorker ¶ added in v0.8.5
func ObserveWorker[T any](iter Iterator[T], fn Observer[T]) WorkerFunc
ObserveWorker has the same semantics as Observe, except that the operation is wrapped in a WaitFunc, and executed when the WaitFunc is called.
func (WorkerFunc) Block ¶ added in v0.8.0
func (wf WorkerFunc) Block() error
Block executes the worker function with a context that will never expire and returns the error. Use with caution
func (WorkerFunc) MustWait ¶ added in v0.8.0
func (wf WorkerFunc) MustWait() WaitFunc
MustWait converts a Worker function into a wait function; however, if the worker produces an error MustWait converts the error into a panic.
func (WorkerFunc) Observe ¶ added in v0.8.0
func (wf WorkerFunc) Observe(ctx context.Context, ob Observer[error])
Observe runs the worker function, and observes the error. Panics are converted to errors for both the worker function but not the observer function.
func (WorkerFunc) ObserveWait ¶ added in v0.8.0
func (wf WorkerFunc) ObserveWait(ob Observer[error]) WaitFunc
ObserveWait converts a worker function into a wait function, passing any error to the observer function. Only non-nil errors are observed.
func (WorkerFunc) Run ¶ added in v0.8.0
func (wf WorkerFunc) Run(ctx context.Context) error
Run is equivalent to calling the worker function directly, except the context passed to it is canceled when the worker function returns.
func (WorkerFunc) Singal ¶ added in v0.8.0
func (wf WorkerFunc) Singal(ctx context.Context) <-chan error
Signal runs the worker function in a background goroutine and returns the error in an error channel, that returns when the worker function returns. If Singal is called with a canceled context the worker is still executed (with that context.)
A value, possibly nil, is always sent through the channel, though the WorkerFunc runs in a different go routine, a panic handler will convert panics to errors.
func (WorkerFunc) WithTimeout ¶ added in v0.8.0
func (wf WorkerFunc) WithTimeout(timeout time.Duration) error
WithTimeout executes the worker function with the provided timeout using a new context.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
Package adt provides "atomic data types" as strongly-typed generic helpers for simple atomic operations (including sync.Map, sync.Pool, and a typed value).
|
Package adt provides "atomic data types" as strongly-typed generic helpers for simple atomic operations (including sync.Map, sync.Pool, and a typed value). |
Package assert provides an incredibly simple assertion framework, that relies on generics and simplicity.
|
Package assert provides an incredibly simple assertion framework, that relies on generics and simplicity. |
check
GENERATED FILE FROM ASSERTION PACKAGE
|
GENERATED FILE FROM ASSERTION PACKAGE |
Package erc provides a simple/fast error aggregation tool for collecting and aggregating errors.
|
Package erc provides a simple/fast error aggregation tool for collecting and aggregating errors. |
Package itertool provides a set of functional helpers for managinging and using fun.Iterator implementations, including a parallel Map/Reduce, Merge, and other convenient tools.
|
Package itertool provides a set of functional helpers for managinging and using fun.Iterator implementations, including a parallel Map/Reduce, Merge, and other convenient tools. |
Package pubsub provides a message broker for one-to-many or many-to-many message distribution.
|
Package pubsub provides a message broker for one-to-many or many-to-many message distribution. |
Package seq provides single and double linked-list implementations and tools (e.g.
|
Package seq provides single and double linked-list implementations and tools (e.g. |
Package Set provides ordered and unordered set implementations for arbitrary comparable types.
|
Package Set provides ordered and unordered set implementations for arbitrary comparable types. |
Package srv provides a framework and toolkit for service orchestration.
|
Package srv provides a framework and toolkit for service orchestration. |
Package testt (for test tools), provides a couple of useful helpers for common test patterns.
|
Package testt (for test tools), provides a couple of useful helpers for common test patterns. |