diff --git a/repeat.go b/repeat.go index 121428e..49649a0 100644 --- a/repeat.go +++ b/repeat.go @@ -1,11 +1,23 @@ package gcf type repeatIteratable[T any] struct { - itb Iteratable[T] + v T count int } type repeatIterator[T any] struct { + v T + count int + i int + current T +} + +type repeatIteratableIteratable[T any] struct { + itb Iteratable[T] + count int +} + +type repeatIteratableIterator[T any] struct { genIt func() Iterator[T] it Iterator[T] count int @@ -13,22 +25,63 @@ type repeatIterator[T any] struct { current T } -func Repeat[T any](itb Iteratable[T], count int) Iteratable[T] { - if itb == nil { - itb = empty[T]() - count = 0 +// Repeat makes Iteratable that repeat v a count times. +// +// itb = gcf.Repeat(1, 3) +// +// If count is 0 or negative, return Iteratable with no element. +func Repeat[T any](v T, count int) Iteratable[T] { + switch { + case count < 1: + return empty[T]() + case count == 1: + return FromSlice([]T{v}) } - if count == 1 { - return itb - } - return &repeatIteratable[T]{itb, count} + return &repeatIteratable[T]{v, count} } func (itb *repeatIteratable[T]) Iterator() Iterator[T] { - return &repeatIterator[T]{itb.itb.Iterator, itb.itb.Iterator(), itb.count, 0, zero[T]()} + return &repeatIterator[T]{itb.v, itb.count, 0, zero[T]()} } func (it *repeatIterator[T]) MoveNext() bool { + if it.i >= it.count { + it.current = zero[T]() + return false + } + it.current = it.v + it.i++ + return true +} + +func (it *repeatIterator[T]) Current() T { + return it.current +} + +// RepeatIteratable makes Iteratable that repeat elements in itb a count times. +// +// s := []int{1, 2, 3} +// itb := gcf.FromSlice(s) +// itb = gcf.RepeatIteratable(itb, 3) +// +// If count is 0 or negative, return Iteratable with no element. +func RepeatIteratable[T any](itb Iteratable[T], count int) Iteratable[T] { + switch { + case itb == nil: + return empty[T]() + case count < 1: + return empty[T]() + case count == 1: + return itb + } + return &repeatIteratableIteratable[T]{itb, count} +} + +func (itb *repeatIteratableIteratable[T]) Iterator() Iterator[T] { + return &repeatIteratableIterator[T]{itb.itb.Iterator, itb.itb.Iterator(), itb.count, 0, zero[T]()} +} + +func (it *repeatIteratableIterator[T]) MoveNext() bool { if it.i >= it.count { return false } @@ -44,6 +97,6 @@ func (it *repeatIterator[T]) MoveNext() bool { return false } -func (it *repeatIterator[T]) Current() T { +func (it *repeatIteratableIterator[T]) Current() T { return it.current } diff --git a/repeat_test.go b/repeat_test.go index bf6e5c2..abc52e0 100644 --- a/repeat_test.go +++ b/repeat_test.go @@ -1,6 +1,7 @@ package gcf_test import ( + "fmt" "testing" "github.com/meian/gcf" @@ -8,6 +9,55 @@ import ( ) func TestRepeat(t *testing.T) { + tests := []struct { + name string + v int + count int + want []int + }{ + { + name: "3 times", + v: 1, + count: 3, + want: []int{1, 1, 1}, + }, + { + name: "1 times", + v: 1, + count: 1, + want: []int{1}, + }, + { + name: "0 times", + v: 1, + count: 0, + want: []int{}, + }, + { + name: "negative times", + v: 1, + count: -1, + want: []int{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert := assert.New(t) + itb := gcf.Repeat(tt.v, tt.count) + s := gcf.ToSlice(itb) + assert.Equal(tt.want, s) + }) + } +} + +func ExampleRepeat() { + itb := gcf.Repeat(1, 3) + fmt.Println(gcf.ToSlice(itb)) + // Output: + // [1 1 1] +} + +func TestRepeatIteratable(t *testing.T) { itb := gcf.FromSlice([]int{1, 2, 3}) itbe := gcf.FromSlice[int](nil) tests := []struct { @@ -34,6 +84,12 @@ func TestRepeat(t *testing.T) { count: 3, want: []int{}, }, + { + name: "1 times", + itb: itb, + count: 1, + want: []int{1, 2, 3}, + }, { name: "0 times", itb: itb, @@ -41,18 +97,27 @@ func TestRepeat(t *testing.T) { want: []int{}, }, { - name: "1 times", + name: "negative times", itb: itb, - count: 1, - want: []int{1, 2, 3}, + count: -1, + want: []int{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert := assert.New(t) - itb := gcf.Repeat(tt.itb, tt.count) + itb := gcf.RepeatIteratable(tt.itb, tt.count) s := gcf.ToSlice(itb) assert.Equal(tt.want, s) }) } } + +func ExampleRepeatIteratable() { + s := []int{1, 2, 3} + itb := gcf.FromSlice(s) + itb = gcf.RepeatIteratable(itb, 3) + fmt.Println(gcf.ToSlice(itb)) + // Output: + // [1 2 3 1 2 3 1 2 3] +}