map<K, V>, a high-level type that represents TVM dictionaries. K denotes the key type, and V denotes the value type.
- Keys and values must be serializable.
- Provides built-in iteration in forward and reverse order, as well as from a specified key.
- No runtime overhead compared to using low-level dictionaries directly.
Create an empty map
Add values to a map
Usem.set(k, v) and the following methods:
Get a value by key
m.get(key) returns isFound + loadValue():
r.isFound, not r == null. map.get(key) does not return V?, but a dedicated result type.
Alternatively, use m.mustGet(key), which returns V and throws if the key is missing:
Iterate forward and backward
There is no dedicatedforeach syntax. Iteration follows this pattern:
- Define a starting key using
m.findFirst()orm.findLast(). - While
r.isFound:- use
r.getKey()andr.loadValue(); - advance the cursor using
m.iterateNext(r)orm.iteratePrev(r).
- use
Check if a map is empty
NULL. However, since map is a dedicated type, it must be checked using isEmpty().
Nullable maps var m: map<...>? are valid. In this case, m may be null, or it may hold either an empty or a non-empty map.
Allowed types for keys and values
The following key and value types are valid:- Keys must be fixed-width and contain no references.
- Valid:
int32,address,bits256,Point. - Invalid:
int,coins,cell.
- Valid:
- Values must be serializable.
- Valid:
coins,AnyStruct,Cell<AnyStruct>. - Invalid:
int,builder.
- Valid:
intN, uintN, or address. Values can be any serializable type.
Available methods for maps
createEmptyMap<K, V>(): map<K, V>
PUSHNULL, since TVM NULL represents an empty map.
createMapFromLowLevelDict<K, V>(d: dict): map<K, V>
map.get or related methods.
m.toLowLevelDict(): dict
m.isEmpty(): bool
m.isEmpty() instead of m == null.
m.exists(key: K): bool
m.get(key: K): MapLookupResult<V>
isFound = false if key does not exist.
m.mustGet(key: K, throwIfNotFound: int = 9): V
m.set(key: K, value: V): self
self, calls may be chained.
m.setAndGetPrevious(key: K, value: V): MapLookupResult<V>
isFound = false.
m.replaceIfExists(key: K, value: V): bool
m.replaceAndGetPrevious(key: K, value: V): MapLookupResult<V>
m.addIfNotExists(key: K, value: V): bool
true if added.
m.addOrGetExisting(key: K, value: V): MapLookupResult<V>
m.delete(key: K): bool
true if deleted.
m.deleteAndGetDeleted(key: K): MapLookupResult<V>
isFound = false.
m.findFirst(): MapEntry<K, V>m.findLast(): MapEntry<K, V>
isFound = false when the map is empty.
m.findKeyGreater(pivotKey: K): MapEntry<K, V>m.findKeyGreaterOrEqual(pivotKey: K): MapEntry<K, V>m.findKeyLess(pivotKey: K): MapEntry<K, V>m.findKeyLessOrEqual(pivotKey: K): MapEntry<K, V>
pivotKey.
m.iterateNext(current: MapEntry<K, V>): MapEntry<K, V>m.iteratePrev(current: MapEntry<K, V>): MapEntry<K, V>
Augmented hashmaps and prefix dictionaries
These structures are rarely used and are not part of the Tolk type system.- Augmented hashmaps and Merkle proofs: implement interaction manually.
- Prefix dictionaries:
import @stdlib/tvm-dictsand use assembly functions.
Keys are auto-serialized
At the TVM level, keys can be numbers or slices. Complex keys, such asPoint, are automatically serialized and deserialized by the compiler.
intN field, it is treated as a number.
Emulate Set<T> with maps
A set can be represented using a map with a unit value type:
map<T, ()> to emulate a set works, but it exposes the full map API, while a set has an API consisting of 4 functions. To avoid this, create a simple wrapper:
isFound instead of optional values
Maps support nullable value types, for example:
- the key exists, and the value is
null; - the key does not exist.
V?, these cases could not be distinguished, because both would result in null.
This becomes visible at the TVM level. At the TVM level, a dictionary reads return binary data as slices. The stack contains either:
(slice -1)when the key is found;(null 0)when the key is not found.
V? would require decoding the value and additional checks to determine whether the key existed:
null:
V?:
isFound, and the value is decoded only when needed.
Usage:
MapLookupResult directly corresponds to the (slice -1) or (null 0) values returned by TVM dictionary operations and avoids additional runtime checks required when returning V?.
Stack layout and serialization
- An empty map is represented as TVM
NULLand is serialized as0. - A non-empty map is represented as a TVM
CELLand is serialized as1followed by a reference.