std / Extensions / Hash_Map
Available on macOS, Linux, Windows, Wasm· since 0.23.0
#import "Extensions/Hash_Map";
An opt-in hash map that probes sixteen slots at a time.
Map :: #import "Extensions/Hash_Map" ;
ages: Map.Map(string , int );
defer Map.deinit (*ages);
Map.insert (*ages, "ada" , 36 );
age := Map.get (*ages, "ada" );
for value, name: ages print("% is %\n" , name, value);
Iteration order is whatever the layout gives, and changes whenever the map grows.
Module parameters#
SCALAR_GROUPS := false Compare the sixteen control bytes of a group with the vector unit. Set it to true to use plain
loops instead (wasm targets always do), which gives the same answers.
Procedures#
(map: *
Map , key: map.Key, value: map.Value) -> (previous: map.Value, replaced:
bool )
Stores the value under the key. Returns the value it replaced (zero if there was none) and
whether there was one.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
_, replaced := Hash_Map.insert (*map, "a" , 1 );
assert (!replaced);
previous, replaced2 := Hash_Map.insert (*map, "a" , 2 );
assert (replaced2 && previous == 1 );Reset Copy ↗ Run ▸
(map: *
Map , key: map.Key) -> *map.Value
A pointer to the key's value, or null if it is missing. The pointer stays valid until the map
is next rebuilt by an insert or entry.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, "hits" , 1 );
hits := Hash_Map.find (*map, "hits" );
hits.* += 1 ;
assert (Hash_Map.get (*map, "hits" ) == 2 );
assert (Hash_Map.find (*map, "misses" ) == null );Reset Copy ↗ Run ▸
(map: *
Map , key: map.Key, default: map.Value = .{}) -> map.Value
A copy of the key's value, or default if it is missing.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, "a" , 1 );
assert (Hash_Map.get (*map, "a" ) == 1 );
assert (Hash_Map.get (*map, "b" , -1 ) == -1 );Reset Copy ↗ Run ▸
(map: *
Map , key: map.Key) -> (value: *map.Value, added:
bool )
A pointer to the key's value, adding a zero-initialized one if the key is missing. added
says whether it was added. Handy for counting.
Hash_Map :: #import "Extensions/Hash_Map" ;
counts: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*counts);
for word: string .["a" , "b" , "a" ] {
count := Hash_Map.entry (*counts, word);
count.* += 1 ;
}
assert (Hash_Map.get (*counts, "a" ) == 2 );Reset Copy ↗ Run ▸
(map: *
Map , key: map.Key) -> (value: map.Value, removed:
bool )
Removes the key. Returns its value (zero if it was missing) and whether it was there.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, "a" , 1 );
value, removed := Hash_Map.delete (*map, "a" );
assert (removed && value == 1 && map.count == 0 );Reset Copy ↗ Run ▸
(map: *
Map , key: map.Key) ->
bool
Whether the key is in the map.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, "a" , 1 );
assert (Hash_Map.contains (*map, "a" ) && !Hash_Map.contains (*map, "b" ));Reset Copy ↗ Run ▸
(map: *
Map , expected_count:
s64 )
Room for expected_count entries in total, so inserting up to that many never rebuilds the map.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(int , int );
defer Hash_Map.deinit (*map);
Hash_Map.reserve (*map, 1000 );
capacity := map.capacity;
for 0 ..999 Hash_Map.insert (*map, it, it);
assert (map.capacity == capacity);Reset Copy ↗ Run ▸
Removes every entry and keeps the memory.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(int , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, 1 , 1 );
Hash_Map.clear (*map);
assert (map.count == 0 && map.capacity > 0 );Reset Copy ↗ Run ▸
Removes every entry and frees the memory. The map can be used again afterwards.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(int , int );
Hash_Map.insert (*map, 1 , 1 );
Hash_Map.deinit (*map);
assert (map.count == 0 && map.capacity == 0 );Reset Copy ↗ Run ▸
(map: *$T/
Map , body:
Code , flags: For_Flags)
for value, key: map {...} visits every entry: it is the value (a pointer to it under
for *), it_index the key. remove it takes the current entry out. Anything else that
changes the map inside the loop, adding included, invalidates the loop.
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(int , int );
defer Hash_Map.deinit (*map);
for 1 ..5 Hash_Map.insert (*map, it, it * 10 );
for value, key: map if key % 2 == 0 remove value;
total := 0 ;
for value: map total += value;
assert (total == 90 );Reset Copy ↗ Run ▸
Types#
:: struct
A hash map from Key to Value. Strings and anything Hash.get_hash handles work as keys
out of the box; pass hash and equal for other types. The zero value is an empty map that
allocates on the first insert; free it with deinit .
count : int Entries in the map. Read only.
capacity : int Slots in the map: zero before the first insert, then a power of two, at least GROUP_SIZE.
Read only.
growth_left : int Empty slots that may still be filled before the map has to be rebuilt.
allocator : Allocator
control : *u8 One byte per slot, followed in the same allocation by the entries.
entries : *Entry
Hash_Map :: #import "Extensions/Hash_Map" ;
map: Hash_Map.Map(string , int );
defer Hash_Map.deinit (*map);
Hash_Map.insert (*map, "one" , 1 );
assert (map.count == 1 && Hash_Map.get (*map, "one" ) == 1 );Reset Copy ↗ Run ▸
Constants#