{
"title": "containers.Map",
"category": "containers/map",
"keywords": [
"containers.Map",
"map",
"dictionary",
"hash map",
"lookup"
],
"summary": "Create MATLAB-compatible dictionary objects that map keys to values.",
"references": [
"https://www.mathworks.com/help/matlab/ref/containers.map-class.html"
],
"gpu_support": {
"elementwise": false,
"reduction": false,
"precisions": [],
"broadcasting": "none",
"notes": "Map storage lives on the host. GPU inputs are gathered when constructing maps or fetching values."
},
"fusion": {
"elementwise": false,
"reduction": false,
"max_inputs": 0,
"constants": "inline"
},
"requires_feature": null,
"tested": {
"unit": "builtins::containers::map::containers_map::tests"
},
"description": "`containers.Map` builds dictionary objects that associate unique keys with values. Keys can be character vectors, string scalars, or numeric scalars (./logical). Values default to MATLAB's `'any'` semantics, letting you store arbitrary scalars, arrays, structs, or handle objects. Each map tracks insertion order, supports key-based indexing, and exposes methods such as `keys`, `values`, `isKey`, and `remove`.",
"behaviors": [
"Keys must be unique. Constructing a map or assigning a key that already exists overwrites the stored value (matching MATLAB's behaviour).",
"The `KeyType`, `ValueType`, and `Count` properties are readable with dot-indexing.",
"`map(key)` returns the associated value; requesting a missing key raises the MATLAB-compatible error *\"The specified key is not present in this container.\"*",
"Assignments of the form `map(key) = value` update or insert entries.",
"Methods `keys(map)`, `values(map)`, `isKey(map, keySpec)`, and `remove(map, keySpec)` are fully compatible. When `keySpec` is a cell or string array, the result matches MATLAB's shape.",
"GPU tensors presented as values are gathered to host memory before insertion. When values or keys arrive on the GPU and need to be expanded element-wise (for example, vector-valued constructor arguments), RunMat downloads them to materialise individual scalars.",
"The `'UniformValues'` flag is accepted; when `true`, RunMat validates that every inserted value has the same MATLAB class. Retrieval still returns a cell array, matching MATLAB behaviour when the value type is `'any'`."
],
"examples": [
{
"description": "Create an empty map with default types",
"input": "m = containers.Map();\nm.KeyType\nm.ValueType\nm.Count",
"output": "ans =\n 'char'\nans =\n 'any'\nans =\n 0"
},
{
"description": "Build a map from paired cell arrays",
"input": "keys = {'apple', 'pear', 'banana'};\nvals = {42, [1 2 3], true};\nfruit = containers.Map(keys, vals);\nenergy = fruit('apple')",
"output": "energy =\n 42"
},
{
"description": "Update an existing key and add a new one",
"input": "fruit('apple') = 99;\nfruit('peach') = struct('ripe', true)",
"output": "fruit('apple')\nans =\n 99"
},
{
"description": "Query keys, values, and membership",
"input": "allKeys = keys(fruit);\nallVals = values(fruit);\nmask = isKey(fruit, {'apple', 'durian'})",
"output": "allKeys =\n 1×4 cell array\n {'apple'} {'pear'} {'banana'} {'peach'}\n\nallVals =\n 1×4 cell array\n {[99]} {[1 2 3]} {[1]} {1×1 struct}\n\nmask =\n 1×2 logical array\n 1 0"
},
{
"description": "Remove keys and inspect the map length",
"input": "remove(fruit, {'pear', 'banana'});\nn = length(fruit);\nremaining = keys(fruit)",
"output": "n =\n 2\nremaining =\n 1×2 cell array\n {'apple'} {'peach'}"
}
],
"faqs": [
{
"question": "Which key types are supported?",
"answer": "`containers.Map` accepts `'char'`, `'string'`, `'double'`, `'single'`, `'int32'`, `'uint32'`, `'int64'`, `'uint64'`, and `'logical'`. Keys supplied during construction or assignment are coerced to the declared type and must be scalar."
},
{
"question": "What happens when I provide duplicate keys at construction time?",
"answer": "Duplicate keys raise the same error as MATLAB: *\"Duplicate key name was provided.\"* During assignment, duplicate keys overwrite the existing value."
},
{
"question": "Does RunMat honour `'UniformValues', true`?",
"answer": "Yes. When this option is set, RunMat enforces that each inserted value matches the MATLAB class of the first value. Retrieval still uses cell arrays, mirroring MATLAB when `'ValueType'` is `'any'`."
},
{
"question": "Can I store GPU arrays as map values?",
"answer": "Yes. RunMat automatically gathers GPU tensors to host memory before inserting them so it can apply the same validation and coercion rules as MATLAB. This ensures constructors that rely on vector expansion continue to produce predictable host-side values."
},
{
"question": "How does `length(map)` behave?",
"answer": "`length(map)` returns the number of stored keys (identical to the `Count` property). `size(map)` remains `[1 1]`, matching MATLAB's handle semantics."
},
{
"question": "What error is raised when a key is missing?",
"answer": "Indexing a missing key produces the MATLAB-compatible error message *\"The specified key is not present in this container.\"*"
},
{
"question": "Does the map preserve insertion order?",
"answer": "Yes. `keys(map)` and `values(map)` return entries in the order they were first inserted, matching the behaviour of MATLAB's `containers.Map`."
},
{
"question": "Is the implementation thread-safe?",
"answer": "Yes. A global read/write lock guards the backing storage so concurrent reads are allowed while write operations remain exclusive."
},
{
"question": "How do I remove every entry?",
"answer": "Call `remove(map, keys(map))` or reassign a new empty map. RunMat currently keeps the internal storage until the handle is cleared, matching MATLAB's lifetime semantics."
},
{
"question": "What happens if I pass a non-scalar key?",
"answer": "Keys must be scalar. Passing vectors, matrices, or nested cell arrays of keys raises a descriptive error pointing to the offending argument."
},
{
"question": "How do I create an empty `containers.Map`?",
"answer": "— Call the constructor with no arguments: `m = containers.Map()`. This yields an empty map with the default `'char'` KeyType and `'any'` ValueType. To pin the types up front (so the first insertion can't change them), supply them explicitly: `m = containers.Map('KeyType', 'char', 'ValueType', 'double')`. Either form gives you a map you can populate via `m(key) = value`."
},
{
"question": "What is the default KeyType and ValueType?",
"answer": "— The default `KeyType` is `'char'` and the default `ValueType` is `'any'`. That is why `containers.Map()` with no arguments accepts character-vector keys and arbitrary values. To use numeric keys (for example `double` or `int32`) or to restrict values to a specific class, set `'KeyType'`/`'ValueType'` at construction time — they become read-only properties afterwards."
},
{
"question": "Can I use MATLAB `string` values as `containers.Map` keys?",
"answer": "— MATLAB's `containers.Map` only accepts scalar character vectors (or scalar numerics / logicals) as keys, not `string` scalars. Convert first with `char(str)` when you use a `'char'` KeyType, e.g. `m(char(\"apple\")) = 1`. RunMat additionally accepts `'string'` as a `KeyType` alias that stores keys as character vectors internally, so either `m = containers.Map('KeyType','char','ValueType','any')` followed by `m(char(s)) = v` or constructing from cell arrays of char vectors works reliably across both runtimes."
},
{
"question": "Is `containers.Map` a handle class?",
"answer": "— Yes. `containers.Map` inherits from `handle`, so maps have **reference semantics**: if you assign `m2 = m1`, both variables point to the same underlying map and mutations through either handle are visible through the other. To get an independent copy, rebuild the map from `keys(m1)` and `values(m1)` (for example, `m2 = containers.Map(keys(m1), values(m1))`). MATLAB does not expose a public `copy` method on `containers.Map`."
}
],
"links": [
{
"label": "length",
"url": "./length"
}
],
"source": {
"label": "`crates/runmat-runtime/src/builtins/containers/map/containers.map.rs`",
"url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/containers/map/containers.map.rs"
},
"gpu_behavior": [
"The data structure itself resides on the CPU. When you construct a map with GPU arrays, RunMat first downloads the inputs so it can perform MATLAB-compatible validation and coercion. Maps never retain device buffers internally, so the GPU provider does not need to implement special hooks for this builtin."
],
"syntax": {
"example": {
"description": "Syntax",
"input": "m = containers.Map()\nm = containers.Map(keys, values)\nm = containers.Map(keys, values, 'UniformValues', tf)\nm = containers.Map('KeyType', ktype, 'ValueType', vtype)"
},
"points": [
"`keys` is a cell vector (or string array) of scalar keys. Every element must share the same `KeyType`; mixing classes raises an error.",
"`values` is a matched cell vector of the values to store, one per key. When `'UniformValues'` is `true`, every value must share the same MATLAB class.",
"`ktype` (the `'KeyType'` Name-Value pair) selects the key class. Supported values are `'char'` (default), `'double'`, `'single'`, `'int32'`, `'uint32'`, `'int64'`, `'uint64'`, and `'logical'`. RunMat additionally accepts `'string'`, storing keys as char vectors internally for MATLAB compatibility.",
"`vtype` (the `'ValueType'` Name-Value pair) restricts the values. The default `'any'` stores arbitrary MATLAB objects; pass a class name (e.g. `'double'`) to reject mismatched inserts.",
"Returns `m`, a handle to a `containers.Map` object. Because it is a handle class, assigning `m2 = m` produces two references to the same map."
]
}
}