-
Notifications
You must be signed in to change notification settings - Fork 1
/
ops.go
269 lines (234 loc) · 6.04 KB
/
ops.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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
package gana
import "golang.org/x/exp/constraints"
// Min returns the minimum of two numbers.
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
// Max returns the maximum of two numbers.
func Max[T constraints.Ordered](a, b T) T {
if a > b {
return a
}
return b
}
// Less is the default less function for any ordered type and will
// return true if a < b, false otherwise.
//
//go:inline
func Less[T constraints.Ordered](a, b T) bool { return a < b }
// DefaultLess is the default greater function for any ordered type and will
// return true if a > b, false otherwise.
//
//go:inline
func Greater[T constraints.Ordered](a, b T) bool { return a > b }
// Equals is the default equals function for any ordered type and will
// return true if a = b, false otherwise.
//
//go:inline
func Equals[T comparable](a, b T) bool { return a == b }
// Equals is the default equals function that will return a closure equals
// function to compare the value to the original wrapped val.
//
//go:inline
func EqualsClosure[T comparable](a T) func(T) bool { return func(b T) bool { return a == b } }
// Minv returns the minimum of the given values, or if no values are given, the zero value of the type.
//
//go:inline
func Minv[T constraints.Ordered](vals ...T) T {
return Minf(Less[T], vals...)
}
// Minf returns the minimum of the given values with a given "less" comparator,
// or if no values are given, the zero value of the type.
func Minf[T any](less func(T, T) bool, vals ...T) T {
if len(vals) == 0 {
return ZeroValue[T]()
}
min := vals[0]
for _, v := range vals {
if less(v, min) {
min = v
}
}
return min
}
// Maxv returns the maximum of the given values, or if no values are given, the zero value of the type.
//
//go:inline
func Maxv[T constraints.Ordered](vals ...T) T {
return Maxf(Less[T], vals...)
}
// Maxf returns the maximum of the given values with a given "less" comparator,
// or if no values are given, the zero value of the type.
func Maxf[T any](less func(T, T) bool, vals ...T) T {
if len(vals) == 0 {
return ZeroValue[T]()
}
max := vals[0]
for _, v := range vals {
if !less(v, max) {
max = v
}
}
return max
}
// MinMaxv returns the minimum and maximum of the given values, or if no values are given, two zero value of the type.
//
//go:inline
func MinMaxv[T constraints.Ordered](vals ...T) (T, T) {
return MinMaxf(Less[T], vals...)
}
// MinMaxv returns the minimum and maximum of the given values with a given "less" comparator,
// or if no values are given, two zero value of the type.
func MinMaxf[T any](less func(T, T) bool, vals ...T) (T, T) {
if len(vals) == 0 {
return ZeroValue[T](), ZeroValue[T]()
}
min := vals[0]
max := vals[0]
for _, v := range vals {
if less(v, min) {
min = v
}
if !less(v, max) {
max = v
}
}
return min, max
}
// First returns the first element of the given array, zero value otherwise.
func First[T any](x []T) T {
if len(x) == 0 {
return ZeroValue[T]()
}
return x[0]
}
// Last returns the last element of the given array, zero value otherwise.
func Last[T any](x []T) T {
l := len(x)
if l == 0 {
return ZeroValue[T]()
}
return x[l-1]
}
// ZeroValue returns the zero value of any type.
//
//go:inline
func ZeroValue[T any]() T {
var t T
return t
}
// Map calls the function on every array element and returns results in list.
func Map[T, S any](f func(T) S, arr []T) []S {
what := make([]S, len(arr))
for i, v := range arr {
what[i] = f(v)
}
return what
}
// Filter calls the function and returns list of values that returned true.
func Filter[T any](f func(T) bool, arr []T) []T {
what := make([]T, 0, len(arr))
for _, v := range arr {
if !f(v) {
continue
}
what = append(what, v)
}
return what
}
// RemoveIf calls the function and returns list of values that returned false.
func RemoveIf[T any](f func(T) bool, arr []T) []T {
what := make([]T, 0, len(arr))
for _, v := range arr {
if f(v) {
continue
}
what = append(what, v)
}
return what
}
// Take returns up to the first `num` elements.
func Take[T any](num int, arr []T) []T {
if len(arr) < num {
return arr
}
return arr[:num]
}
// Tail returns up to the last `num` elements.
func Tail[T any](num int, arr []T) []T {
if len(arr) < num {
return arr
}
return arr[len(arr)-num:]
}
// Drop allocates a new slice, with the first `num` elements dropped.
func Drop[T any, U constraints.Unsigned](num U, arr []T) []T {
l := U(len(arr))
if l < num {
return []T{}
}
slice := make([]T, l-num)
copy(slice, arr[num:])
return slice
}
// Skips skips the first `num` elements by slicing (underlying array unaffected).
func Skip[T any, U constraints.Unsigned](num U, arr []T) []T {
if U(len(arr)) < num {
return arr[:0]
}
return arr[num:]
}
// Zip returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument lists.
func Zip[T, U any](a []T, b []U) []Tuple[T, U] {
l := Min(len(a), len(b))
what := make([]Tuple[T, U], l)
for i := 0; i < l; i++ {
what[i] = NewTuple(a[i], b[i])
}
return what
}
// Any returns true if any element in the list matches the given value.
//
//go:inline
func Any[T comparable](val T, arr []T) bool {
return Anyf(EqualsClosure(val), arr)
}
// Anyf returns true if any elemens in the list returns true when passed to foo.
func Anyf[T any](foo func(v T) bool, arr []T) bool {
for _, v := range arr {
if foo(v) {
return true
}
}
return false
}
// All returns true if all elements in the list match the given value.
//
//go:inline
func All[T comparable](val T, arr []T) bool {
return Allf(EqualsClosure(val), arr)
}
// Allf returns true if all elements in the array return true when passed to foo.
func Allf[T any](foo func(v T) bool, arr []T) bool {
for _, v := range arr {
if !foo(v) {
return false
}
}
return true
}
// Repeat creates a list of given size consisting of the same given value.
func Repeat[T any](val T, size int) []T {
arr := make([]T, size)
for i := range arr {
arr[i] = val
}
return arr
}
// GetPointer returns the pointer of a given lhs.
func GetPointer[T any](val T) *T {
return &val
}