Skip to content

Latest commit

 

History

History
110 lines (81 loc) · 4.09 KB

README.md

File metadata and controls

110 lines (81 loc) · 4.09 KB

Go Reference CI workflow

go-functional

Functional programming primitives and OTP-inspired concurrency patterns for Go generics.

Requires Go 1.24+. See the documentation site for full API docs and examples.

Installation

go get github.com/mikehelmick/go-functional

Packages

Functional primitives

Package Description
slice Filter, Map, Fold, Find, Zip, Chunk, Sort, Dedup, Scan, and more
maps MapValues, FilterMap, Merge, MergeWith, Invert, Keys, ToSlice
optional Maybe[T] — Some or None with Map and GetOrElse
result Result[T] — wraps (T, error) with Map and chaining
pipeline Function composition: Pipe, Pipe2, Pipe3, Pipe4

OTP-inspired concurrency

Inspired by Elixir's OTP abstractions. Each package provides a typed, goroutine-safe building block.

Package Description
agent Goroutine-owned mutable state with Get / Update / Cast
genserver Generic request/response server loop — Call (sync) and Cast (async)
task Typed async work unit — Run, Await, AwaitAll, Map
supervisor Managed goroutine restart with OneForOne and OneForAll strategies

Quick examples

Slice operations

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

evens  := slice.Filter(nums, func(n int) bool { return n%2 == 0 })  // [2 4 6]
doubled := slice.Map(nums, func(n int) int { return n * 2 })         // [2 4 6 8 10 12]
sum    := slice.FoldL(nums, 0, func(acc, n int) int { return acc + n }) // 21
top3   := slice.Take(slice.SortBy(nums, func(n int) int { return -n }), 3) // [6 5 4]

Task — concurrent work

tasks := []*task.Task[int]{
    task.Run(func() (int, error) { return expensiveA() }),
    task.Run(func() (int, error) { return expensiveB() }),
    task.Run(func() (int, error) { return expensiveC() }),
}
results, err := task.AwaitAll(tasks) // waits for all, returns in order

Agent — shared mutable state

counter := agent.New(0)
counter.Update(func(n int) int { return n + 1 })
fmt.Println(counter.Get()) // 1
counter.Stop()

Supervisor — automatic restart

sup := supervisor.Start(supervisor.OneForOne, []supervisor.ChildSpec{
    {
        Name: "worker",
        Start: func(ctx context.Context) error {
            // Runs until ctx is cancelled.
            // Returning a non-nil error triggers an automatic restart.
            return runWorker(ctx)
        },
    },
})
defer sup.Stop()

GenServer — serialised state with call/cast

type CounterServer struct{}

func (CounterServer) Init() int                                  { return 0 }
func (CounterServer) HandleCall(req string, n int) (int, int)    { return n, n } // return current
func (CounterServer) HandleCast(req string, n int) int           { return n + 1 } // increment

srv := genserver.Start[int, string, int](CounterServer{})
srv.Cast("inc")
srv.Cast("inc")
fmt.Println(srv.Call("get")) // 2
srv.Stop()

Example application

See examples/wordfreq for an OTP-style word frequency service that combines supervisor, agent, task, pipeline, slice, and maps.

Attribution

Parts of this library were written with the assistance of Claude Code.