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) }