master
Jordan Orelli 3 years ago
parent f4afff43cd
commit ff53acaa2e

@ -0,0 +1,52 @@
package iter
import "constraints"
// Able is anything that is iter.Able
type Able[T any] interface {
Iter() Ator[T]
}
// Ator is an iter.Ator
type Ator[T any] interface {
// Next assigns the value pointed at by *T to the next value in the
// iteration. Next should return true if a value was set. An Ator that
// returns false should continue to return false; once iteration is
// complete it should be complete forever.
Next(*T) bool
}
func Ate[T any](a Able[T]) (T, Ator[T]) {
var v T
return v, a.Iter()
}
func Min[T constraints.Ordered](it Ator[T]) T {
var v T
if !it.Next(&v) {
var zero T
return zero
}
min := v
for it.Next(&v) {
if v < min {
min = v
}
}
return min
}
func Max[T constraints.Ordered](it Ator[T]) T {
var v T
if !it.Next(&v) {
var zero T
return zero
}
max := v
for it.Next(&v) {
if v > max {
max = v
}
}
return max
}

@ -0,0 +1,30 @@
package iter
import (
"constraints"
)
type span[T constraints.Integer] struct {
next T
final T
step T
}
func (s *span[T]) Next(n *T) bool {
if s.next >= s.final {
return false
}
*n = s.next
s.next += s.step
return true
}
// Span creates a span of integers between start and end
func Span[T constraints.Integer](start, end T) Ator[T] {
return &span[T]{next: start, final: 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) Ator[T] {
return &span[T]{next: start, final: end, step: step}
}

@ -0,0 +1,37 @@
package iter
import (
"testing"
)
func TestSpan(t *testing.T) {
var n int
s := Span(1, 10)
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)
}
}
func TestStep(t *testing.T) {
s := Step(1, 10, 3)
for n := 0; s.Next(&n); {
t.Log(n)
}
}

@ -8,6 +8,10 @@ type Iter[T any] interface {
Next(*T) bool
}
// for v, it := iter.Ate(foods); it.Next(&v); {
//
// }
// This actually works, but for some reason I don't yet understand, defining
// Max with a constraint of constrains.Ordered that takes Iterable[T] cannot
// have its type parameter infered, but defining it with the same constraint of

@ -41,6 +41,9 @@ func Make[T any](vals ...T) List[T] {
return l
}
// func From[T any](it iter.Able) List[T] {
// }
// Empty is true for empty lists
func (l List[T]) Empty() bool {
return l.head == nil

@ -41,6 +41,18 @@ func TestOne(t *testing.T) {
if l.Len() != 1 {
t.Errorf("expected a list of size 1 but saw %d instead", l.Len())
}
if n := l.Pop(); n != 3 {
t.Errorf("popping first element from the list should be 3 but is %d instead", n)
}
if !l.Empty() {
t.Errorf("new list is not empty, but should be")
}
if l.Len() != 0 {
t.Errorf("expected a list of size 0 but saw %d instead", l.Len())
}
}
func TestMake(t *testing.T) {

Loading…
Cancel
Save