@@ -35,138 +35,143 @@ import (
35
35
type threadUnsafeSet [T comparable ] map [T ]struct {}
36
36
37
37
// Assert concrete type:threadUnsafeSet adheres to Set interface.
38
- var _ Set [string ] = (* threadUnsafeSet [string ])(nil )
38
+ var _ Set [string ] = (threadUnsafeSet [string ])(nil )
39
39
40
40
func newThreadUnsafeSet [T comparable ]() threadUnsafeSet [T ] {
41
41
return make (threadUnsafeSet [T ])
42
42
}
43
43
44
- func (s * threadUnsafeSet [T ]) Add (v T ) bool {
45
- prevLen := len (* s )
46
- ( * s ) [v ] = struct {}{}
47
- return prevLen != len (* s )
44
+ func (s threadUnsafeSet [T ]) Add (v T ) bool {
45
+ prevLen := len (s )
46
+ s [v ] = struct {}{}
47
+ return prevLen != len (s )
48
48
}
49
49
50
50
// private version of Add which doesn't return a value
51
- func (s * threadUnsafeSet [T ]) add (v T ) {
52
- ( * s ) [v ] = struct {}{}
51
+ func (s threadUnsafeSet [T ]) add (v T ) {
52
+ s [v ] = struct {}{}
53
53
}
54
54
55
- func (s * threadUnsafeSet [T ]) Cardinality () int {
56
- return len (* s )
55
+ func (s threadUnsafeSet [T ]) Cardinality () int {
56
+ return len (s )
57
57
}
58
58
59
- func (s * threadUnsafeSet [T ]) Clear () {
60
- * s = newThreadUnsafeSet [T ]()
59
+ func (s threadUnsafeSet [T ]) Clear () {
60
+ // Constructions like this are optimised by compiler, and replaced by
61
+ // mapclear() function, defined in
62
+ // https://github.com/golang/go/blob/29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4/src/runtime/map.go#L993)
63
+ for key := range s {
64
+ delete (s , key )
65
+ }
61
66
}
62
67
63
- func (s * threadUnsafeSet [T ]) Clone () Set [T ] {
68
+ func (s threadUnsafeSet [T ]) Clone () Set [T ] {
64
69
clonedSet := make (threadUnsafeSet [T ], s .Cardinality ())
65
- for elem := range * s {
70
+ for elem := range s {
66
71
clonedSet .add (elem )
67
72
}
68
- return & clonedSet
73
+ return clonedSet
69
74
}
70
75
71
- func (s * threadUnsafeSet [T ]) Contains (v ... T ) bool {
76
+ func (s threadUnsafeSet [T ]) Contains (v ... T ) bool {
72
77
for _ , val := range v {
73
- if _ , ok := ( * s ) [val ]; ! ok {
78
+ if _ , ok := s [val ]; ! ok {
74
79
return false
75
80
}
76
81
}
77
82
return true
78
83
}
79
84
80
85
// private version of Contains for a single element v
81
- func (s * threadUnsafeSet [T ]) contains (v T ) bool {
82
- _ , ok := ( * s ) [v ]
86
+ func (s threadUnsafeSet [T ]) contains (v T ) ( ok bool ) {
87
+ _ , ok = s [v ]
83
88
return ok
84
89
}
85
90
86
- func (s * threadUnsafeSet [T ]) Difference (other Set [T ]) Set [T ] {
87
- o := other .(* threadUnsafeSet [T ])
91
+ func (s threadUnsafeSet [T ]) Difference (other Set [T ]) Set [T ] {
92
+ o := other .(threadUnsafeSet [T ])
88
93
89
94
diff := newThreadUnsafeSet [T ]()
90
- for elem := range * s {
95
+ for elem := range s {
91
96
if ! o .contains (elem ) {
92
97
diff .add (elem )
93
98
}
94
99
}
95
- return & diff
100
+ return diff
96
101
}
97
102
98
- func (s * threadUnsafeSet [T ]) Each (cb func (T ) bool ) {
99
- for elem := range * s {
103
+ func (s threadUnsafeSet [T ]) Each (cb func (T ) bool ) {
104
+ for elem := range s {
100
105
if cb (elem ) {
101
106
break
102
107
}
103
108
}
104
109
}
105
110
106
- func (s * threadUnsafeSet [T ]) Equal (other Set [T ]) bool {
107
- o := other .(* threadUnsafeSet [T ])
111
+ func (s threadUnsafeSet [T ]) Equal (other Set [T ]) bool {
112
+ o := other .(threadUnsafeSet [T ])
108
113
109
114
if s .Cardinality () != other .Cardinality () {
110
115
return false
111
116
}
112
- for elem := range * s {
117
+ for elem := range s {
113
118
if ! o .contains (elem ) {
114
119
return false
115
120
}
116
121
}
117
122
return true
118
123
}
119
124
120
- func (s * threadUnsafeSet [T ]) Intersect (other Set [T ]) Set [T ] {
121
- o := other .(* threadUnsafeSet [T ])
125
+ func (s threadUnsafeSet [T ]) Intersect (other Set [T ]) Set [T ] {
126
+ o := other .(threadUnsafeSet [T ])
122
127
123
128
intersection := newThreadUnsafeSet [T ]()
124
129
// loop over smaller set
125
130
if s .Cardinality () < other .Cardinality () {
126
- for elem := range * s {
131
+ for elem := range s {
127
132
if o .contains (elem ) {
128
133
intersection .add (elem )
129
134
}
130
135
}
131
136
} else {
132
- for elem := range * o {
137
+ for elem := range o {
133
138
if s .contains (elem ) {
134
139
intersection .add (elem )
135
140
}
136
141
}
137
142
}
138
- return & intersection
143
+ return intersection
139
144
}
140
145
141
- func (s * threadUnsafeSet [T ]) IsProperSubset (other Set [T ]) bool {
146
+ func (s threadUnsafeSet [T ]) IsProperSubset (other Set [T ]) bool {
142
147
return s .Cardinality () < other .Cardinality () && s .IsSubset (other )
143
148
}
144
149
145
- func (s * threadUnsafeSet [T ]) IsProperSuperset (other Set [T ]) bool {
150
+ func (s threadUnsafeSet [T ]) IsProperSuperset (other Set [T ]) bool {
146
151
return s .Cardinality () > other .Cardinality () && s .IsSuperset (other )
147
152
}
148
153
149
- func (s * threadUnsafeSet [T ]) IsSubset (other Set [T ]) bool {
150
- o := other .(* threadUnsafeSet [T ])
154
+ func (s threadUnsafeSet [T ]) IsSubset (other Set [T ]) bool {
155
+ o := other .(threadUnsafeSet [T ])
151
156
if s .Cardinality () > other .Cardinality () {
152
157
return false
153
158
}
154
- for elem := range * s {
159
+ for elem := range s {
155
160
if ! o .contains (elem ) {
156
161
return false
157
162
}
158
163
}
159
164
return true
160
165
}
161
166
162
- func (s * threadUnsafeSet [T ]) IsSuperset (other Set [T ]) bool {
167
+ func (s threadUnsafeSet [T ]) IsSuperset (other Set [T ]) bool {
163
168
return other .IsSubset (s )
164
169
}
165
170
166
- func (s * threadUnsafeSet [T ]) Iter () <- chan T {
171
+ func (s threadUnsafeSet [T ]) Iter () <- chan T {
167
172
ch := make (chan T )
168
173
go func () {
169
- for elem := range * s {
174
+ for elem := range s {
170
175
ch <- elem
171
176
}
172
177
close (ch )
@@ -175,12 +180,12 @@ func (s *threadUnsafeSet[T]) Iter() <-chan T {
175
180
return ch
176
181
}
177
182
178
- func (s * threadUnsafeSet [T ]) Iterator () * Iterator [T ] {
183
+ func (s threadUnsafeSet [T ]) Iterator () * Iterator [T ] {
179
184
iterator , ch , stopCh := newIterator [T ]()
180
185
181
186
go func () {
182
187
L:
183
- for elem := range * s {
188
+ for elem := range s {
184
189
select {
185
190
case <- stopCh :
186
191
break L
@@ -193,77 +198,78 @@ func (s *threadUnsafeSet[T]) Iterator() *Iterator[T] {
193
198
return iterator
194
199
}
195
200
196
- // TODO: how can we make this properly , return T but can't return nil.
197
- func (s * threadUnsafeSet [T ]) Pop () (v T , ok bool ) {
198
- for item := range * s {
199
- delete (* s , item )
201
+ // Pop returns a popped item in case set is not empty, or nil-value of T
202
+ // if set is already empty
203
+ func (s threadUnsafeSet [T ]) Pop () (v T , ok bool ) {
204
+ for item := range s {
205
+ delete (s , item )
200
206
return item , true
201
207
}
202
- return
208
+ return v , false
203
209
}
204
210
205
- func (s * threadUnsafeSet [T ]) Remove (v T ) {
206
- delete (* s , v )
211
+ func (s threadUnsafeSet [T ]) Remove (v T ) {
212
+ delete (s , v )
207
213
}
208
214
209
- func (s * threadUnsafeSet [T ]) String () string {
210
- items := make ([]string , 0 , len (* s ))
215
+ func (s threadUnsafeSet [T ]) String () string {
216
+ items := make ([]string , 0 , len (s ))
211
217
212
- for elem := range * s {
218
+ for elem := range s {
213
219
items = append (items , fmt .Sprintf ("%v" , elem ))
214
220
}
215
221
return fmt .Sprintf ("Set{%s}" , strings .Join (items , ", " ))
216
222
}
217
223
218
- func (s * threadUnsafeSet [T ]) SymmetricDifference (other Set [T ]) Set [T ] {
219
- o := other .(* threadUnsafeSet [T ])
224
+ func (s threadUnsafeSet [T ]) SymmetricDifference (other Set [T ]) Set [T ] {
225
+ o := other .(threadUnsafeSet [T ])
220
226
221
227
sd := newThreadUnsafeSet [T ]()
222
- for elem := range * s {
228
+ for elem := range s {
223
229
if ! o .contains (elem ) {
224
230
sd .add (elem )
225
231
}
226
232
}
227
- for elem := range * o {
233
+ for elem := range o {
228
234
if ! s .contains (elem ) {
229
235
sd .add (elem )
230
236
}
231
237
}
232
- return & sd
238
+ return sd
233
239
}
234
240
235
- func (s * threadUnsafeSet [T ]) ToSlice () []T {
241
+ func (s threadUnsafeSet [T ]) ToSlice () []T {
236
242
keys := make ([]T , 0 , s .Cardinality ())
237
- for elem := range * s {
243
+ for elem := range s {
238
244
keys = append (keys , elem )
239
245
}
240
246
241
247
return keys
242
248
}
243
249
244
- func (s * threadUnsafeSet [T ]) Union (other Set [T ]) Set [T ] {
245
- o := other .(* threadUnsafeSet [T ])
250
+ func (s threadUnsafeSet [T ]) Union (other Set [T ]) Set [T ] {
251
+ o := other .(threadUnsafeSet [T ])
246
252
247
253
n := s .Cardinality ()
248
254
if o .Cardinality () > n {
249
255
n = o .Cardinality ()
250
256
}
251
257
unionedSet := make (threadUnsafeSet [T ], n )
252
258
253
- for elem := range * s {
259
+ for elem := range s {
254
260
unionedSet .add (elem )
255
261
}
256
- for elem := range * o {
262
+ for elem := range o {
257
263
unionedSet .add (elem )
258
264
}
259
- return & unionedSet
265
+ return unionedSet
260
266
}
261
267
262
268
// MarshalJSON creates a JSON array from the set, it marshals all elements
263
- func (s * threadUnsafeSet [T ]) MarshalJSON () ([]byte , error ) {
269
+ func (s threadUnsafeSet [T ]) MarshalJSON () ([]byte , error ) {
264
270
items := make ([]string , 0 , s .Cardinality ())
265
271
266
- for elem := range * s {
272
+ for elem := range s {
267
273
b , err := json .Marshal (elem )
268
274
if err != nil {
269
275
return nil , err
@@ -277,7 +283,7 @@ func (s *threadUnsafeSet[T]) MarshalJSON() ([]byte, error) {
277
283
278
284
// UnmarshalJSON recreates a set from a JSON array, it only decodes
279
285
// primitive types. Numbers are decoded as json.Number.
280
- func (s * threadUnsafeSet [T ]) UnmarshalJSON (b []byte ) error {
286
+ func (s threadUnsafeSet [T ]) UnmarshalJSON (b []byte ) error {
281
287
var i []any
282
288
283
289
d := json .NewDecoder (bytes .NewReader (b ))
0 commit comments