Skip to main content
Version: v2.2.82 (latest)
Reference · Collections

Array

Functional operations for Go slices. Comprehensive set of operations treating slices as immutable data structures with type-safe transformations.

01

Overview

The array package provides functional operations for Go slices:

  • Immutable: Always returns new slices
  • Type-safe: Leverages Go generics
  • Composable: Chain operations together
basic.go
import A "github.com/IBM/fp-go/v2/array"

// Create arrays
numbers := A.From(1, 2, 3, 4, 5)
single := A.Of(42)
empty := A.Empty[int]()

// Transform
doubled := A.Map(func(n int) int { return n * 2 })(numbers)
// []int{2, 4, 6, 8, 10}

// Filter
evens := A.Filter(func(n int) bool { return n%2 == 0 })(numbers)
// []int{2, 4}

// Reduce
sum := A.Reduce(func(acc, n int) int { return acc + n }, 0)(numbers)
// 15
02

Core API

Constructors

FunctionSignatureDescription
Fromfunc From[A any](values ...A) []ACreate from variadic args
Offunc Of[A any](value A) []ASingle element array
Emptyfunc Empty[A any]() []AEmpty array
MakeByfunc MakeBy[A any](n int, f func(int) A) []AGenerate with function
Replicatefunc Replicate[A any](n int, value A) []ARepeat value n times

Transformations

FunctionSignatureDescription
Mapfunc Map[A, B any](f func(A) B) func([]A) []BTransform each element
MapWithIndexfunc MapWithIndex[A, B any](f func(int, A) B) func([]A) []BMap with index
Chainfunc Chain[A, B any](f func(A) []B) func([]A) []BFlatMap
FilterMapfunc FilterMap[A, B any](f func(A) Option[B]) func([]A) []BFilter and map

Filtering

FunctionSignatureDescription
Filterfunc Filter[A any](pred func(A) bool) func([]A) []AKeep matching elements
FilterWithIndexfunc FilterWithIndex[A any](pred func(int, A) bool) func([]A) []AFilter with index
Partitionfunc Partition[A any](pred func(A) bool) func([]A) Pair[[]A, []A]Split into two arrays

Reduction

FunctionSignatureDescription
Reducefunc Reduce[A, B any](f func(B, A) B, initial B) func([]A) BFold left
ReduceRightfunc ReduceRight[A, B any](f func(A, B) B, initial B) func([]A) BFold right
ReduceWithIndexfunc ReduceWithIndex[A, B any](f func(int, B, A) B, initial B) func([]A) BReduce with index

Access

FunctionSignatureDescription
Headfunc Head[A any]([]A) Option[A]First element
Lastfunc Last[A any]([]A) Option[A]Last element
Tailfunc Tail[A any]([]A) Option[[]A]All but first
Lookupfunc Lookup[A any](index int) func([]A) Option[A]Element at index

Combining

FunctionSignatureDescription
Appendfunc Append[A any](arr []A, value A) []AAdd to end
Prependfunc Prepend[A any](value A) func([]A) []AAdd to start
Flattenfunc Flatten[A any]([][]A) []AFlatten nested arrays
Concatfunc Concat[A any](arrays ...[]A) []AConcatenate arrays

Checking

FunctionSignatureDescription
IsEmptyfunc IsEmpty[A any]([]A) boolCheck if empty
IsNonEmptyfunc IsNonEmpty[A any]([]A) boolCheck if non-empty
Sizefunc Size[A any]([]A) intGet length
Elemfunc Elem[A any](eq Eq[A]) func(A) func([]A) boolCheck if contains
03

Usage Examples

Basic Transformations

transformations.go
import (
  A "github.com/IBM/fp-go/v2/array"
  F "github.com/IBM/fp-go/v2/function"
)

numbers := []int{1, 2, 3, 4, 5}

// Map
doubled := F.Pipe2(
  numbers,
  A.Map(func(n int) int { return n * 2 }),
)
// []int{2, 4, 6, 8, 10}

// Filter
evens := F.Pipe2(
  numbers,
  A.Filter(func(n int) bool { return n%2 == 0 }),
)
// []int{2, 4}

// Reduce
sum := F.Pipe2(
  numbers,
  A.Reduce(func(acc, n int) int { return acc + n }, 0),
)
// 15

Chain (FlatMap)

chain.go
type User struct {
  Name  string
  Roles []string
}

users := []User{
  {Name: "Alice", Roles: []string{"admin", "user"}},
  {Name: "Bob", Roles: []string{"user"}},
}

// Get all roles
allRoles := F.Pipe2(
  users,
  A.Chain(func(u User) []string { return u.Roles }),
)
// []string{"admin", "user", "user"}

FilterMap

filtermap.go
import O "github.com/IBM/fp-go/v2/option"

numbers := []int{1, 2, 3, 4, 5}

// Keep even numbers and double them
result := F.Pipe2(
  numbers,
  A.FilterMap(func(n int) O.Option[int] {
      if n%2 == 0 {
          return O.Some(n * 2)
      }
      return O.None[int]()
  }),
)
// []int{4, 8}

Partition

partition.go
numbers := []int{1, 2, 3, 4, 5, 6}

// Separate evens and odds
result := F.Pipe2(
  numbers,
  A.Partition(func(n int) bool { return n%2 == 0 }),
)

odds := result.Head   // []int{1, 3, 5}
evens := result.Tail  // []int{2, 4, 6}

Real-World Example

products.go
type Product struct {
  ID       int
  Name     string
  Price    float64
  Category string
  InStock  bool
}

products := []Product{
  {ID: 1, Name: "Laptop", Price: 999.99, Category: "Electronics", InStock: true},
  {ID: 2, Name: "Mouse", Price: 29.99, Category: "Electronics", InStock: true},
  {ID: 3, Name: "Desk", Price: 299.99, Category: "Furniture", InStock: false},
  {ID: 4, Name: "Chair", Price: 199.99, Category: "Furniture", InStock: true},
}

// Get names of in-stock electronics under $500
result := F.Pipe3(
  products,
  A.Filter(func(p Product) bool {
      return p.InStock && p.Category == "Electronics" && p.Price < 500
  }),
  A.Map(func(p Product) string { return p.Name }),
  A.Sort(ord.FromCompare(strings.Compare)),
)
// []string{"Mouse"}

// Calculate total value of in-stock items
totalValue := F.Pipe3(
  products,
  A.Filter(func(p Product) bool { return p.InStock }),
  A.Reduce(func(sum float64, p Product) float64 {
      return sum + p.Price
  }, 0.0),
)
// 1429.97
04

Common Patterns

Safe Head

safe_head.go
// Instead of: arr[0] (panics if empty)
head := F.Pipe2(
  arr,
  A.Head,
  O.GetOrElse(func() int { return 0 }),
)

Transform and Aggregate

aggregate.go
// Map then reduce
result := F.Pipe4(
  numbers,
  A.Map(func(n int) int { return n * n }),
  A.Filter(func(n int) bool { return n > 10 }),
  A.Reduce(func(sum, n int) int { return sum + n }, 0),
)

Conditional Transformation

conditional.go
// Use FilterMap for conditional transforms
result := F.Pipe2(
  items,
  A.FilterMap(func(item Item) O.Option[Result] {
      if item.IsValid() {
          return O.Some(item.Transform())
      }
      return O.None[Result]()
  }),
)

Best Practices:

  • Use Pipe for readability when chaining operations
  • Prefer immutability - array functions return new slices
  • Combine operations with FilterMap instead of separate Filter + Map
  • Check for empty with IsEmpty before accessing elements