array — interface-first slice
github.com/go-composites/array (Go package Array, imported from the src/
sub-directory) is an interface-first wrapper around a []interface{}. Every
method returns a result, so it composes with the rest of the org,
and each method has a package-level twin that operates on a plain
[]interface{} without constructing an Array.
API
import Array "github.com/go-composites/array/src"
type Interface interface {
Each(fn func(int, interface{}) Result.Interface) Result.Interface
Map(fn func(int, interface{}) Result.Interface) Result.Interface
Filter(pred func(int, interface{}) Result.Interface) Result.Interface
Reduce(seed interface{}, fn func(acc, item interface{}) Result.Interface) Result.Interface
Find(pred func(int, interface{}) Result.Interface) Result.Interface
Any(pred func(int, interface{}) Result.Interface) Result.Interface
All(pred func(int, interface{}) Result.Interface) Result.Interface
Push(interface{}) Result.Interface
Pop() Result.Interface
First() Result.Interface
Fetch(int) Result.Interface
Last() Result.Interface
Clear() Result.Interface
Copy() Result.Interface
Len() int
IsEmpty() bool
Contains(item interface{}) Result.Interface
Insert(index int, item interface{}) Result.Interface
Delete(index int) Result.Interface
Reverse() Result.Interface
Sort(less func(a, b interface{}) bool) Result.Interface
IndexOf(item interface{}) Result.Interface
Slice(start, end int) Result.Interface
IsNull() bool
}
func New() Interface
// Null-Object variant (honours the full Interface, never nil):
func Null() Interface
// Package-level twins over a raw []interface{}:
func Each(items []interface{}, fn func(int, interface{}) Result.Interface) Result.Interface
func Map(items []interface{}, fn func(int, interface{}) Result.Interface) Result.Interface
func Filter(items []interface{}, pred func(int, interface{}) Result.Interface) Result.Interface
func Reduce(items []interface{}, seed interface{}, fn func(acc, item interface{}) Result.Interface) Result.Interface
func Find(items []interface{}, pred func(int, interface{}) Result.Interface) Result.Interface
func Any(items []interface{}, pred func(int, interface{}) Result.Interface) Result.Interface
func All(items []interface{}, pred func(int, interface{}) Result.Interface) Result.Interface
func Sort(items []interface{}, less func(a, b interface{}) bool) Result.Interface
func IndexOf(items []interface{}, item interface{}) Result.Interface
func Slice(items []interface{}, start, end int) Result.Interface
Accessors and mutators
| Method | Behaviour |
|---|---|
Push(x) |
Appends x; returns a result whose payload is the array itself. |
Pop() |
Removes and returns the last element as the result payload. Panics if the array is empty. |
First() |
Returns element 0 as the payload. Panics if empty. |
Fetch(i) |
Returns element i as the payload. Panics if i is out of range. |
Last() |
Returns the last element (d.value[len-1]) as the payload. Panics if empty. |
Clear() |
Resets to an empty slice; returns an empty result. |
Copy() |
Returns a result whose payload is a new, independent Array (the backing slice is copied, so mutating one does not affect the other). |
Len() |
Returns the number of elements as a Go int. |
IsEmpty() |
Returns a Go bool: true when the array has no elements. |
Contains(x) |
Returns a result whose payload is a Go bool: true when x is present (compared with reflect.DeepEqual). |
Insert(i, x) |
Inserts x at index i, shifting the tail right (i == Len() appends). Payload is the array itself; an out-of-range i yields a result carrying an Error ("Array.Insert: index out of range"). |
Delete(i) |
Removes the element at index i, shifting the tail left. Payload is the removed item; an out-of-range i yields a result carrying an Error ("Array.Delete: index out of range"). |
Reverse() |
Reverses the array in place; payload is the array itself. |
Sort(less) |
Sorts the array in place with sort.SliceStable (so the order is stable) using less(a, b); payload is the array itself. |
IndexOf(x) |
Returns a result whose payload is a Go int: the index of the first element equal to x (compared with reflect.DeepEqual), or -1 when no element matches. |
Slice(start, end) |
Returns a result whose payload is a new, independent Array holding the elements [start:end). An out-of-range request (start < 0, end > Len(), or start > end) yields a result carrying an Error ("Array.Slice: index out of range"). |
IsNull() |
Returns false for a real array (see the Null-Object note below). |
Bounds are not guarded
Pop, First, Fetch, and Last index the underlying slice directly and
will panic on an out-of-range access (e.g. on an empty array). They do
not convert the panic into an error result. By contrast, the newer
Insert and Delete do validate their index and report an out-of-range
access as an Error result.
Null-Object variant
Array.Null() returns the Null-Object array: an empty, immutable
placeholder that honours the full Interface without ever being nil.
Mutating methods are no-ops returning a successful result, lookups and
queries return empty/false/zero values (Len() == 0, IsEmpty() == true),
and IsNull() returns true. Use it instead of a nil Array.Interface.
Iteration and combinators
All combinators take callbacks that return a result and
short-circuit on the first result whose HasError() == true (a real error),
returning that error result unchanged. On a full, error-free pass each returns a
result describing the outcome.
| Method | Behaviour |
|---|---|
Each(fn) |
Calls fn(index, item) for its side effects. Returns the first error result, or an empty result. |
Map(fn) |
Collects each callback's payload into a new Array. Payload is the new Array.Interface. |
Filter(pred) |
Keeps items whose pred payload is truthy, into a new Array. Payload is the new Array.Interface. |
Reduce(seed, fn) |
Left fold threading an accumulator (fn(acc, item)); payload is the final accumulator. |
Find(pred) |
First item whose pred payload is truthy (as payload). No match → a result carrying an Error. |
Any(pred) |
Payload is a Go bool: true on the first truthy item, else false. Empty array → false. |
All(pred) |
Payload is a Go bool: false on the first falsy item, else true. Empty array → true (vacuous). |
Truthiness
Filter, Find, Any, and All decide whether a predicate's payload counts
as a match via isTruthy:
- a Go
boolis its own value; - any value exposing an
IsTrue() boolmethod (for example aBoolean.Interface) uses that result — this is matched structurally, soarraydoes not importboolean(which would form an import cycle); nilis falsy;- any other non-nil payload is truthy.
Usage
arr := Array.New()
arr.Push(1)
arr.Push(2)
arr.Push(3)
// Map: double every item into a new Array.
doubled := arr.Map(func(_ int, item interface{}) Result.Interface {
return Result.New(Result.WithPayload(item.(int) * 2))
})
out := doubled.Payload().(Array.Interface) // [2 4 6]
// Reduce: sum the items.
sum := arr.Reduce(0, func(acc, item interface{}) Result.Interface {
return Result.New(Result.WithPayload(acc.(int) + item.(int)))
})
total := sum.Payload().(int) // 6
// Any / All over a predicate.
hasEven := arr.Any(func(_ int, item interface{}) Result.Interface {
return Result.New(Result.WithPayload(item.(int)%2 == 0))
})
yes := hasEven.Payload().(bool) // true
// Find: first matching item, or a not-found Error.
r := arr.Find(func(_ int, item interface{}) Result.Interface {
return Result.New(Result.WithPayload(item.(int) > 1))
})
if r.HasError() {
fmt.Println(r.Error().Message()) // "Array.Find: no matching item"
} else {
fmt.Println(r.Payload()) // 2
}
The package-level twins behave identically over a raw slice, e.g.
Array.Map(items, fn) or Array.Reduce(items, seed, fn).
Dependencies
array depends on result and error (the latter for
Find's not-found sentinel), and transitively on null.