github.com/mitranim/gg@v0.1.17/map.go (about) 1 package gg 2 3 /* 4 Non-idempotent version of `MapInit`. If the target pointer is nil, does nothing 5 and returns nil. If the target pointer is non-nil, allocates the map via 6 `make`, stores it at the target pointer, and returns the resulting non-nil 7 map. 8 */ 9 func MapMake[Map ~map[Key]Val, Key comparable, Val any](ptr *Map) Map { 10 if ptr == nil { 11 return nil 12 } 13 val := make(map[Key]Val) 14 *ptr = val 15 return val 16 } 17 18 /* 19 Shortcut for converting an arbitrary map to `Dict`. Workaround for the 20 limitations of type inference in Go generics. This is a free cast with no 21 reallocation. 22 */ 23 func ToDict[Src ~map[Key]Val, Key comparable, Val any](val Src) Dict[Key, Val] { 24 return Dict[Key, Val](val) 25 } 26 27 /* 28 Typedef of an arbitrary map with various methods that duplicate global map 29 functions. Useful as a shortcut for creating bound methods that can be passed 30 to higher-order functions. 31 */ 32 type Dict[Key comparable, Val any] map[Key]Val 33 34 // Same as `len(self)`. 35 func (self Dict[_, _]) Len() int { return len(self) } 36 37 // Same as `len(self) <= 0`. Inverse of `.IsNotEmpty`. 38 func (self Dict[_, _]) IsEmpty() bool { return len(self) <= 0 } 39 40 // Same as `len(self) > 0`. Inverse of `.IsEmpty`. 41 func (self Dict[_, _]) IsNotEmpty() bool { return len(self) > 0 } 42 43 /* 44 Idempotent map initialization. If the target pointer is nil, does nothing and 45 returns nil. If the map at the target pointer is non-nil, does nothing and 46 returns that map. Otherwise allocates the map via `make`, stores it at the 47 target pointer, and returns the resulting non-nil map. 48 */ 49 func MapInit[Map ~map[Key]Val, Key comparable, Val any](ptr *Map) Map { 50 if ptr == nil { 51 return nil 52 } 53 val := *ptr 54 if val == nil { 55 val = make(map[Key]Val) 56 *ptr = val 57 } 58 return val 59 } 60 61 // Self as global `MapInit`. 62 func (self *Dict[Key, Val]) Init() Dict[Key, Val] { return MapInit(self) } 63 64 /* 65 Copies the given map. If the input is nil, the output is nil. Otherwise the 66 output is a shallow copy. 67 */ 68 func MapClone[Map ~map[Key]Val, Key comparable, Val any](src Map) Map { 69 if src == nil { 70 return nil 71 } 72 73 out := make(Map, len(src)) 74 for key, val := range src { 75 out[key] = val 76 } 77 return out 78 } 79 80 // Self as global `MapClone`. 81 func (self Dict[Key, Val]) Clone() Dict[Key, Val] { return MapClone(self) } 82 83 // Returns the maps's keys as a slice. Order is random. 84 func MapKeys[Key comparable, Val any](src map[Key]Val) []Key { 85 if src == nil { 86 return nil 87 } 88 89 out := make([]Key, 0, len(src)) 90 for key := range src { 91 out = append(out, key) 92 } 93 return out 94 } 95 96 // Self as global `MapKeys`. 97 func (self Dict[Key, _]) Keys() []Key { return MapKeys(self) } 98 99 // Returns the maps's values as a slice. Order is random. 100 func MapVals[Key comparable, Val any](src map[Key]Val) []Val { 101 if src == nil { 102 return nil 103 } 104 105 out := make([]Val, 0, len(src)) 106 for _, val := range src { 107 out = append(out, val) 108 } 109 return out 110 } 111 112 // Self as global `MapVals`. 113 func (self Dict[_, Val]) Vals() []Val { return MapVals(self) } 114 115 // Same as `_, ok := tar[key]`, expressed as a generic function. 116 func MapHas[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key) bool { 117 _, ok := tar[key] 118 return ok 119 } 120 121 // Self as global `MapHas`. 122 func (self Dict[Key, _]) Has(key Key) bool { return MapHas(self, key) } 123 124 // Same as `val, ok := tar[key]`, expressed as a generic function. 125 func MapGot[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key) (Val, bool) { 126 val, ok := tar[key] 127 return val, ok 128 } 129 130 // Self as global `MapGot`. 131 func (self Dict[Key, Val]) Got(key Key) (Val, bool) { return MapGot(self, key) } 132 133 // Same as `tar[key]`, expressed as a generic function. 134 func MapGet[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key) Val { 135 return tar[key] 136 } 137 138 // Self as global `MapGet`. 139 func (self Dict[Key, Val]) Get(key Key) Val { return MapGet(self, key) } 140 141 // Same as `tar[key] = val`, expressed as a generic function. 142 func MapSet[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key, val Val) { 143 tar[key] = val 144 } 145 146 // Self as global `MapSet`. 147 func (self Dict[Key, Val]) Set(key Key, val Val) { MapSet(self, key, val) } 148 149 /* 150 Same as `MapSet`, but key and value should be be non-zero. 151 If either is zero, this ignores the inputs and does nothing. 152 */ 153 func MapSetOpt[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key, val Val) { 154 if IsNotZero(key) && IsNotZero(val) { 155 MapSet(tar, key, val) 156 } 157 } 158 159 // Self as global `MapSetOpt`. 160 func (self Dict[Key, Val]) SetOpt(key Key, val Val) { MapSetOpt(self, key, val) } 161 162 // Same as `delete(tar, key)`, expressed as a generic function. 163 func MapDel[Map ~map[Key]Val, Key comparable, Val any](tar Map, key Key) { 164 delete(tar, key) 165 } 166 167 // Self as global `MapDel`. 168 func (self Dict[Key, _]) Del(key Key) { delete(self, key) } 169 170 /* 171 Deletes all entries, returning the resulting map. Passing nil is safe. 172 Note that this involves iterating the map, which is inefficient in Go. 173 In many cases, it's more efficient to make a new map. 174 */ 175 func MapClear[Map ~map[Key]Val, Key comparable, Val any](tar Map) { 176 for key := range tar { 177 delete(tar, key) 178 } 179 } 180 181 // Self as global `MapClear`. 182 func (self Dict[_, _]) Clear() { MapClear(self) }