-
Notifications
You must be signed in to change notification settings - Fork 0
/
inflater.go
180 lines (164 loc) · 4.43 KB
/
inflater.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
Package `inflater` provides an `Inflater` interface that inflates a value
into multiple values and some operations to combine them `Inflater`s.
*/
package inflater
import (
"iter"
)
// Inflater is the interface that inflate a value to a sequence of values
type Inflater[V any] interface {
// Inflate a seed value to a sequence of values.
Inflate(seed V) iter.Seq[V]
}
// InflateFunc is a wrapper function for using a function as an Inflater.
type InflaterFunc[V any] func(seed V) iter.Seq[V]
// Inflate a value to a sequence of values.
func (f InflaterFunc[V]) Inflate(seed V) iter.Seq[V] {
return f(seed)
}
// Slice is a wrapper for a slice, which creates an Inflater that returns the
// elements of the slice. This Inflater always ignores the input.
type Slice[V any] []V
// Inflate inflates all elements of the slice. It ignores the input seed.
func (slice Slice[V]) Inflate(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
for _, v := range slice {
if !yield(v) {
return
}
}
}
}
// None provides an Inflater which not inflate anything.
func None[V any]() Inflater[V] {
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {}
})
}
// Keep provides an Inflater which inflate just only seed.
func Keep[V any]() Inflater[V] {
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
yield(seed)
}
})
}
// Map is an Inflater which maps (modify/convert) a value to another value with a function.
func Map[V any](apply func(V) V) Inflater[V] {
if apply == nil {
return Keep[V]()
}
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
if !yield(apply(seed)) {
return
}
}
})
}
// Filter provides an Inflater which pass through a seed if check(seed) returns true.
func Filter[V any](check func(V) bool) Inflater[V] {
if check == nil {
return Keep[V]()
}
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
if check(seed) && !yield(seed) {
return
}
}
})
}
// Parallel2 creates an Inflater that inflates one input with two Inflaters and
// concatenates the results into one iter.Seq.
func Parallel2[V any](first, second Inflater[V]) Inflater[V] {
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
for s := range first.Inflate(seed) {
if !yield(s) {
return
}
}
for s := range second.Inflate(seed) {
if !yield(s) {
return
}
}
}
})
}
// Parallel creates an Inflater that inflates one input with multiple Inflaters
// and concatenates the results into one iter.Seq.
func Parallel[V any](inflaters ...Inflater[V]) Inflater[V] {
switch len(inflaters) {
case 0:
return None[V]()
case 1:
return inflaters[0]
case 2:
return Parallel2(inflaters[0], inflaters[1])
default:
return Parallel2(inflaters[0], Parallel(inflaters[1:]...))
}
}
// Serial2 creates an Inflater that inflates the input with the first Inflater
// and then inflates the result with the second Inflater.
func Serial2[V any](first, second Inflater[V]) Inflater[V] {
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
for s := range first.Inflate(seed) {
for t := range second.Inflate(s) {
if !yield(t) {
return
}
}
}
}
})
}
// Serial creates an Inflater that inflates the input with the first Inflater,
// then inflates the result with the second Inflater, and repeats this for all
// the given Inflaters.
func Serial[V any](inflaters ...Inflater[V]) Inflater[V] {
switch len(inflaters) {
case 0:
return None[V]()
case 1:
return inflaters[0]
case 2:
return Serial2[V](inflaters[0], inflaters[1])
default:
return Serial2[V](inflaters[0], Serial(inflaters[1:]...))
}
}
// Prefix creates an Inflater that prepends each prefix string to one input.
func Prefix[V ~string](prefixes ...V) Inflater[V] {
if len(prefixes) == 0 {
return None[V]()
}
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
for _, prefix := range prefixes {
if !yield(prefix + seed) {
return
}
}
}
})
}
// Suffix creates an Inflater that appends each suffix string to the input.
func Suffix[V ~string](suffixes ...V) Inflater[V] {
if len(suffixes) == 0 {
return None[V]()
}
return InflaterFunc[V](func(seed V) iter.Seq[V] {
return func(yield func(V) bool) {
for _, suffix := range suffixes {
if !yield(seed + suffix) {
return
}
}
}
})
}