Maps ({"a": 1})
Maps in Luma are key–value collections.
They’re the right choice when you want to look things up by a key instead of by index.
Think of them as “dictionaries” or “hash maps” in other languages.
Map Types
Map types use curly braces with a key type and a value type:
{K: V}Some common examples:
{str: int} // map from strings to ints
{int: str} // map from ints to strings
{str: bool} // feature flags by name
{str: Person} // map from username to a Person struct
{str: ?int} // map from string to optional intYou use map types in variable declarations just like any other type:
ages: {str: int}
users: {int: str}
configs: {str: ?int}Map Literals
You create a map value using { key: value, ... }:
ages: {str: int} = {
"Alice": 30,
"Bob": 25,
}
prices: {str: float} = {
"apple": 0.99,
"banana": 1.19,
}A few notes:
- Keys and values can be any valid expressions, as long as they match the declared types.
- Trailing commas are allowed and often make diffs nicer.
- An empty map literal is just
{}but you usually want to give the variable a type so the compiler knows key/value types:
counters: {str: int} = {}Reading Values
Index into a map with map[key]:
ages: {str: int} = {
"Alice": 30,
"Bob": 25,
}
print(ages["Alice"]) // 30
print(ages["Bob"]) // 25urrently, if a key is missing, the underlying Go semantics apply: you’ll get the zero value for the value type (for example 0 for int, "" for str, nil for optional values). In practice, it’s often a good idea to store an optional in the value when you need to distinguish “missing” vs “present but default”.
scores: {str: ?int} = {}
scores["Alice"] = 42
print(scores["Alice"]) // 42
print(scores["Bob"]) // nil (no score recorded)Updating Maps
You assign to a map entry with map[key] = value:
ages: {str: int} = {
"Alice": 30,
}
ages["Alice"] = 31
ages["Bob"] = 22
print(ages["Alice"]) // 31
print(ages["Bob"]) // 22The compiler uses the map’s declared type to generate a correctly-typed Go map behind the scenes, so you get static checking on both keys and values.
Maps With Structs and Optionals
Maps work nicely with the newer struct and optional support.
Map of structs
struct Person {
name: str
age: int
}
people: {str: Person} = {
"alice": Person("Alice", 30),
"bob": Person("Bob", 25),
}
alice: Person = people["alice"]
print(alice.name) // Alice
print(alice.age) // 30Map of optional values
Optional values are useful when “no value yet” is different from “value is zero”.
last_login: {str: ?int} = {}
user: str = "alice"
if last_login[user] == nil {
print("First login for ${user}")
} else {
print("Welcome back, ${user}")
}Lists of Maps
ou can freely combine lists and maps. A common pattern is a list of maps representing rows of data:
rows: [{str: int}] = [
{"year": 2023, "users": 100},
{"year": 2024, "users": 250},
]
rows.walk(row) -> {
print("Year ${row["year"]}, users: ${row["users"]}")
}The parser understands this pattern and treats each { ... } inside the [...] as a map literal.
You can also have:
people_by_city: {str: [str]} = {
"Tallinn": ["Alice", "Bob"],
"Riga": ["Carol"],
}Maps and lists compose cleanly and follow the same type syntax:
[T]- list ofT{K: V}- map fromKtoV?T- optionalT
Gotchas & Tips
- Always give maps an explicit type in declarations.
This lets the compiler generate typed Go maps instead of a genericmap[interface{}]interface{}.
data = {"a": 1} // generic map (less type safety)
data: {str: int} = { // preferred
"a": 1,
}- Missing keys currently behave like Go: you get the zero value.
If you need to distinguish “missing” vs “present”, store an optional value (?T). - Maps are unordered. Don’t rely on iteration order. If you need stable ordering, store keys in a list and sort that list before walking.
This page will grow as Luma’s collection helpers evolve (for example, more map-specific utilities once they’re added to the standard library), but everything above is supported today and should be stable to rely on.