-
Notifications
You must be signed in to change notification settings - Fork 83
/
iter.go
110 lines (96 loc) · 2.96 KB
/
iter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// Package iter implement a generic Iterator.
package iter
// An Iterator is a stream of items of some type.
type Iterator[T any] interface {
// Next checks whether if the iteration has more elements and
// returns the next one if exists.
Next() (T, bool)
}
// FromSlice creates a new iterator which returns all items from the slice starting at index 0 until
// all items are consumed.
func FromSlice[T any](slice []T) Iterator[T] {
return &sliceIterator[T]{slice: slice}
}
type sliceIterator[T any] struct {
slice []T
}
func (iter *sliceIterator[T]) Next() (T, bool) {
if len(iter.slice) == 0 {
var zero T
return zero, false
}
item := iter.slice[0]
iter.slice = iter.slice[1:]
return item, true
}
// Map returns a new iterator which applies a function to all items from the input iterator which
// are subsequently returned.
//
// The mapping function should not mutate the state outside its scope.
func Map[T any, O any](from Iterator[T], mapFunc func(T) O) Iterator[O] {
return &mapIterator[T, O]{from: from, mapFunc: mapFunc}
}
type mapIterator[T any, O any] struct {
from Iterator[T]
mapFunc func(T) O
}
func (iter *mapIterator[T, O]) Next() (O, bool) {
item, ok := iter.from.Next()
if !ok {
var zero O
return zero, false
}
mapped := iter.mapFunc(item)
return mapped, true
}
// Flatten applies a function to all items of the specified iterator, returning an iterator for each
// item. The resulting iterators are then concatenated into a single iterator.
func Flatten[T any](from Iterator[Iterator[T]]) Iterator[T] {
return &flattenIterator[T]{from: from}
}
type flattenIterator[T any] struct {
from Iterator[Iterator[T]]
head Iterator[T]
}
func (iter *flattenIterator[T]) Next() (T, bool) {
for {
if iter.head == nil {
item, ok := iter.from.Next()
if !ok {
var zero T
return zero, false
}
iter.head = item
}
item, ok := iter.head.Next()
if ok {
return item, true
}
iter.head = nil
}
}
// Empty returns an iterator that never returns anything.
func Empty[T any]() Iterator[T] {
return emptyIterator[T]{}
}
type emptyIterator[T any] struct{}
func (emptyIterator[T]) Next() (T, bool) {
var zero T
return zero, false
}