put span in its own package

master
Jordan Orelli 3 years ago
parent 4032920454
commit 9b9c986876

@ -43,6 +43,9 @@ func Start[T any](a Able[T]) (T, Ator[T]) {
return v, a.Iter()
}
// Min gets the minimum value in the iterable collection src. Src must be a
// collection of ordered values. Min requires that src's definition of
// iteration is finite.
func Min[T constraints.Ordered](src Able[T]) T {
it := src.Iter()
var v T
@ -59,6 +62,9 @@ func Min[T constraints.Ordered](src Able[T]) T {
return min
}
// Max gets the maximum value in the iterable collection src. Src must be a
// collection of ordered values. Max requires that src's definition of
// iteration is finite.
func Max[T constraints.Ordered](src Able[T]) T {
it := src.Iter()
var v T

@ -1,58 +0,0 @@
package iter
import (
"constraints"
)
type span[T constraints.Integer] struct {
start T
end T
step T
}
type spanIter[T constraints.Integer] struct {
start T
end T
step T
next T
}
func (s span[T]) Iter() Ator[T] {
return &spanIter[T]{
start: s.start,
end: s.end,
step: s.step,
next: s.start,
}
}
func (s *spanIter[T]) Next(n *T) bool {
if s.next >= s.end {
return false
}
*n = s.next
s.next += s.step
return true
}
func (s spanIter[T]) Iter() Ator[T] { return &s }
// Span creates a span of integers between start and end. The is analagous to
// the "range" function in Python, but since range already means something in
// Go, span is the chosen name to avoid confusion with Go's concept of range.
func Span[T constraints.Integer](start, end T) Able[T] {
return &span[T]{
start: start,
end: end,
step: 1,
}
}
// Step is the same as span, but allows for step sizes greater than 1
func Step[T constraints.Integer](start, end, step T) Able[T] {
return &span[T]{
start: start,
end: end,
step: step,
}
}

@ -1,39 +0,0 @@
package iter
import (
"testing"
)
func TestSpan(t *testing.T) {
var n int
s := Span(1, 10).Iter()
s.Next(&n)
if n != 1 {
t.Errorf("expected n to be 1 but is %d instead", n)
}
for s.Next(&n) {
}
if n != 9 {
t.Errorf("expected n to be 9 but is %d instead", n)
}
beer := Max(Span(1, 100))
if beer != 99 {
t.Errorf("expected 99 beers but saw %d instead", beer)
}
old := Min(Span(30, 40))
if old != 30 {
t.Errorf("expected 30 to be old but saw %d instead", old)
}
t.Logf("%T", Max(Span[uint8](3, 10)))
}
func TestStep(t *testing.T) {
s := Step(1, 10, 3).Iter()
for n := 0; s.Next(&n); {
t.Log(n)
}
}

@ -0,0 +1,61 @@
package span
import (
"constraints"
"github.com/jordanorelli/generic/iter"
)
type Span[T constraints.Integer] struct {
Start T
End T
Step T
}
type spanIter[T constraints.Integer] struct {
start T
end T
step T
next T
}
func (s Span[T]) Iter() iter.Ator[T] {
return &spanIter[T]{
start: s.Start,
end: s.End,
step: s.Step,
next: s.Start,
}
}
func (s *spanIter[T]) Next(n *T) bool {
if s.step == 0 || s.next < s.start || s.next >= s.end {
return false
}
*n = s.next
s.next += s.step
return true
}
func (s spanIter[T]) Iter() iter.Ator[T] { return &s }
// New creates a span of integers between start and end. The is analagous to
// the "range" function in Python, but since range already means something in
// Go, span is the chosen name to avoid confusion with Go's concept of range.
// The created span is given a step size of 1.
func New[T constraints.Integer](start, end T) Span[T] {
return Span[T]{
Start: start,
End: end,
Step: 1,
}
}
// Step is the same as creating a span with a provided step value
func Step[T constraints.Integer](start, end, step T) Span[T] {
return Span[T]{
Start: start,
End: end,
Step: step,
}
}

@ -0,0 +1,48 @@
package span
import (
"testing"
"github.com/jordanorelli/generic/iter"
)
func TestSpan(t *testing.T) {
var n int
it := New(1, 10).Iter()
it.Next(&n)
if n != 1 {
t.Errorf("expected n to be 1 but is %d instead", n)
}
for it.Next(&n) {
}
if n != 9 {
t.Errorf("expected n to be 9 but is %d instead", n)
}
// If the function New returns a value of iter.Able[T], this type parameter
// can be inferred, but when New returns a value of Span[T] (which
// satisfies iter.Able[T]), the type parameter cannot be inferred. I don't
// know why this behavior exists or if this is the intended behavior.
// +
// |
// V
beer := iter.Max[int](New(1, 100))
if beer != 99 {
t.Errorf("expected 99 beers but saw %d instead", beer)
}
old := iter.Min[int](New(30, 40))
if old != 30 {
t.Errorf("expected 30 to be old but saw %d instead", old)
}
t.Logf("%T", iter.Max[int8](New[int8](3, 10)))
}
func TestStep(t *testing.T) {
it := Step(1, 10, 3).Iter()
for n := 0; it.Next(&n); {
t.Log(n)
}
}
Loading…
Cancel
Save