Source file test/typeparam/maps.go

```     1  // run
2
4  // Use of this source code is governed by a BSD-style
6
7  package main
8
9  import (
10  	"fmt"
11  	"math"
12  	"sort"
13  )
14
15  // _Equal reports whether two slices are equal: the same length and all
16  // elements equal. All floating point NaNs are considered equal.
17  func _SliceEqual[Elem comparable](s1, s2 []Elem) bool {
18  	if len(s1) != len(s2) {
19  		return false
20  	}
21  	for i, v1 := range s1 {
22  		v2 := s2[i]
23  		if v1 != v2 {
24  			isNaN := func(f Elem) bool { return f != f }
25  			if !isNaN(v1) || !isNaN(v2) {
26  				return false
27  			}
28  		}
29  	}
30  	return true
31  }
32
33  // _Keys returns the keys of the map m.
34  // The keys will be an indeterminate order.
35  func _Keys[K comparable, V any](m map[K]V) []K {
36  	r := make([]K, 0, len(m))
37  	for k := range m {
38  		r = append(r, k)
39  	}
40  	return r
41  }
42
43  // _Values returns the values of the map m.
44  // The values will be in an indeterminate order.
45  func _Values[K comparable, V any](m map[K]V) []V {
46  	r := make([]V, 0, len(m))
47  	for _, v := range m {
48  		r = append(r, v)
49  	}
50  	return r
51  }
52
53  // _Equal reports whether two maps contain the same key/value pairs.
54  // _Values are compared using ==.
55  func _Equal[K, V comparable](m1, m2 map[K]V) bool {
56  	if len(m1) != len(m2) {
57  		return false
58  	}
59  	for k, v1 := range m1 {
60  		if v2, ok := m2[k]; !ok || v1 != v2 {
61  			return false
62  		}
63  	}
64  	return true
65  }
66
67  // _Copy returns a copy of m.
68  func _Copy[K comparable, V any](m map[K]V) map[K]V {
69  	r := make(map[K]V, len(m))
70  	for k, v := range m {
71  		r[k] = v
72  	}
73  	return r
74  }
75
76  // _Add adds all key/value pairs in m2 to m1. _Keys in m2 that are already
77  // present in m1 will be overwritten with the value in m2.
78  func _Add[K comparable, V any](m1, m2 map[K]V) {
79  	for k, v := range m2 {
80  		m1[k] = v
81  	}
82  }
83
84  // _Sub removes all keys in m2 from m1. _Keys in m2 that are not present
85  // in m1 are ignored. The values in m2 are ignored.
86  func _Sub[K comparable, V any](m1, m2 map[K]V) {
87  	for k := range m2 {
88  		delete(m1, k)
89  	}
90  }
91
92  // _Intersect removes all keys from m1 that are not present in m2.
93  // _Keys in m2 that are not in m1 are ignored. The values in m2 are ignored.
94  func _Intersect[K comparable, V any](m1, m2 map[K]V) {
95  	for k := range m1 {
96  		if _, ok := m2[k]; !ok {
97  			delete(m1, k)
98  		}
99  	}
100  }
101
102  // _Filter deletes any key/value pairs from m for which f returns false.
103  func _Filter[K comparable, V any](m map[K]V, f func(K, V) bool) {
104  	for k, v := range m {
105  		if !f(k, v) {
106  			delete(m, k)
107  		}
108  	}
109  }
110
111  // _TransformValues applies f to each value in m. The keys remain unchanged.
112  func _TransformValues[K comparable, V any](m map[K]V, f func(V) V) {
113  	for k, v := range m {
114  		m[k] = f(v)
115  	}
116  }
117
118  var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16}
119  var m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"}
120
121  func TestKeys() {
122  	want := []int{1, 2, 4, 8}
123
124  	got1 := _Keys(m1)
125  	sort.Ints(got1)
126  	if !_SliceEqual(got1, want) {
127  		panic(fmt.Sprintf("_Keys(%v) = %v, want %v", m1, got1, want))
128  	}
129
130  	got2 := _Keys(m2)
131  	sort.Ints(got2)
132  	if !_SliceEqual(got2, want) {
133  		panic(fmt.Sprintf("_Keys(%v) = %v, want %v", m2, got2, want))
134  	}
135  }
136
137  func TestValues() {
138  	got1 := _Values(m1)
139  	want1 := []int{2, 4, 8, 16}
140  	sort.Ints(got1)
141  	if !_SliceEqual(got1, want1) {
142  		panic(fmt.Sprintf("_Values(%v) = %v, want %v", m1, got1, want1))
143  	}
144
145  	got2 := _Values(m2)
146  	want2 := []string{"16", "2", "4", "8"}
147  	sort.Strings(got2)
148  	if !_SliceEqual(got2, want2) {
149  		panic(fmt.Sprintf("_Values(%v) = %v, want %v", m2, got2, want2))
150  	}
151  }
152
153  func TestEqual() {
154  	if !_Equal(m1, m1) {
155  		panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", m1, m1))
156  	}
157  	if _Equal(m1, nil) {
158  		panic(fmt.Sprintf("_Equal(%v, nil) = true, want false", m1))
159  	}
160  	if _Equal(nil, m1) {
161  		panic(fmt.Sprintf("_Equal(nil, %v) = true, want false", m1))
162  	}
163  	if !_Equal[int, int](nil, nil) {
164  		panic("_Equal(nil, nil) = false, want true")
165  	}
166  	if ms := map[int]int{1: 2}; _Equal(m1, ms) {
167  		panic(fmt.Sprintf("_Equal(%v, %v) = true, want false", m1, ms))
168  	}
169
170  	// Comparing NaN for equality is expected to fail.
171  	mf := map[int]float64{1: 0, 2: math.NaN()}
172  	if _Equal(mf, mf) {
173  		panic(fmt.Sprintf("_Equal(%v, %v) = true, want false", mf, mf))
174  	}
175  }
176
177  func TestCopy() {
178  	m2 := _Copy(m1)
179  	if !_Equal(m1, m2) {
180  		panic(fmt.Sprintf("_Copy(%v) = %v, want %v", m1, m2, m1))
181  	}
182  	m2[16] = 32
183  	if _Equal(m1, m2) {
184  		panic(fmt.Sprintf("_Equal(%v, %v) = true, want false", m1, m2))
185  	}
186  }
187
189  	mc := _Copy(m1)
191  	if !_Equal(mc, m1) {
192  		panic(fmt.Sprintf("_Add(%v, %v) = %v, want %v", m1, m1, mc, m1))
193  	}
195  	want := map[int]int{1: 2, 2: 4, 4: 8, 8: 16, 16: 32}
196  	if !_Equal(mc, want) {
197  		panic(fmt.Sprintf("_Add result = %v, want %v", mc, want))
198  	}
199  }
200
201  func TestSub() {
202  	mc := _Copy(m1)
203  	_Sub(mc, mc)
204  	if len(mc) > 0 {
205  		panic(fmt.Sprintf("_Sub(%v, %v) = %v, want empty map", m1, m1, mc))
206  	}
207  	mc = _Copy(m1)
208  	_Sub(mc, map[int]int{1: 0})
209  	want := map[int]int{2: 4, 4: 8, 8: 16}
210  	if !_Equal(mc, want) {
211  		panic(fmt.Sprintf("_Sub result = %v, want %v", mc, want))
212  	}
213  }
214
215  func TestIntersect() {
216  	mc := _Copy(m1)
217  	_Intersect(mc, mc)
218  	if !_Equal(mc, m1) {
219  		panic(fmt.Sprintf("_Intersect(%v, %v) = %v, want %v", m1, m1, mc, m1))
220  	}
221  	_Intersect(mc, map[int]int{1: 0, 2: 0})
222  	want := map[int]int{1: 2, 2: 4}
223  	if !_Equal(mc, want) {
224  		panic(fmt.Sprintf("_Intersect result = %v, want %v", mc, want))
225  	}
226  }
227
228  func TestFilter() {
229  	mc := _Copy(m1)
230  	_Filter(mc, func(int, int) bool { return true })
231  	if !_Equal(mc, m1) {
232  		panic(fmt.Sprintf("_Filter(%v, true) = %v, want %v", m1, mc, m1))
233  	}
234  	_Filter(mc, func(k, v int) bool { return k < 3 })
235  	want := map[int]int{1: 2, 2: 4}
236  	if !_Equal(mc, want) {
237  		panic(fmt.Sprintf("_Filter result = %v, want %v", mc, want))
238  	}
239  }
240
241  func TestTransformValues() {
242  	mc := _Copy(m1)
243  	_TransformValues(mc, func(i int) int { return i / 2 })
244  	want := map[int]int{1: 1, 2: 2, 4: 4, 8: 8}
245  	if !_Equal(mc, want) {
246  		panic(fmt.Sprintf("_TransformValues result = %v, want %v", mc, want))
247  	}
248  }
249
250  func main() {
251  	TestKeys()
252  	TestValues()
253  	TestEqual()
254  	TestCopy()