From 1fcffb2ea44e0090d74dd0726267a32ab61a6c4b Mon Sep 17 00:00:00 2001 From: "M.V. Hutz" Date: Sat, 7 Feb 2026 21:02:13 -0500 Subject: [PATCH] docs: iterator --- pkg/iterator/iterator.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/pkg/iterator/iterator.go b/pkg/iterator/iterator.go index 2db5cd4..bbcde01 100644 --- a/pkg/iterator/iterator.go +++ b/pkg/iterator/iterator.go @@ -1,35 +1,37 @@ -/* -Package "iterator" -*/ +// Package iterator defines a generic way to iterator over a slice of data. package iterator import "fmt" -// An iterator over slices. +// An Iterator traverses over slices. type Iterator[T any] struct { items []T index int } -// Create a new iterator, over a set of items. +// Of creates a new iterator, over a set of defined items. func Of[T any](items []T) *Iterator[T] { return &Iterator[T]{items: items, index: 0} } -// Returns the current position of the iterator. +// Index returns the current position of the iterator. func (i Iterator[T]) Index() int { return i.index } +// Copy returns a identical clone of the iterator. The underlying data structure +// is not cloned. func (i Iterator[T]) Copy() *Iterator[T] { return &Iterator[T]{items: i.items, index: i.index} } +// Sync returns the iterator to the position of another. It is assumed that the +// iterators both operate on the same set of data. func (i *Iterator[T]) Sync(o *Iterator[T]) { i.index = o.index } -// Create a new iterator, over a set of items. +// Get returns the datum at the current position of the iterator. func (i Iterator[T]) Get() (T, error) { var null T if i.Done() { @@ -39,6 +41,7 @@ func (i Iterator[T]) Get() (T, error) { return i.items[i.index], nil } +// MustGet is a version of Get, that panics if the datum cannot be returned. func (i Iterator[T]) MustGet() T { var null T if i.Done() { @@ -48,13 +51,16 @@ func (i Iterator[T]) MustGet() T { return i.items[i.index] } +// Forward increments the iterator if the iterator is not yet at the end of the +// slice. func (i *Iterator[T]) Forward() { if !i.Done() { i.index++ } } -// Create a new iterator, over a set of items. +// Next attempts to increment the iterator. Returns an error if it cannot be +// incremented. func (i *Iterator[T]) Next() (T, error) { item, err := i.Get() if err == nil { @@ -64,16 +70,20 @@ func (i *Iterator[T]) Next() (T, error) { return item, err } -// Create a new iterator, over a set of items. +// Back decrements the iterator. If the iterator is already at the beginning of +// the slice, this is a no-op. func (i *Iterator[T]) Back() { i.index = max(i.index-1, 0) } -// Returns the current position of the iterator. +// Done returns whether the iterator is at the end of the slice or not. func (i Iterator[T]) Done() bool { return i.index == len(i.items) } +// Do attempts to perform an operation using the iterator. If the operation +// succeeds, the iterator is updated. If the operation fails, the iterator is +// rolled back, and an error is returned. func Do[T any, U any](i *Iterator[T], fn func(i *Iterator[T]) (U, error)) (U, error) { i2 := i.Copy()