Dict is a collection of key/value pairs.

ids = {"Alice": 145, "Bob": 214, "Charlie": 301}
assert ids["Alice"] == 145

The key does not have to be a string if it is a Hashable object.

# deprecated to use a range object as a key (confused with slice)
r = {1..3: "1~3", 4..6: "4~6", 7..9: "7~9"}
assert r[1..3] == "1~3"
l = {[]: "empty", [1]: "1"}
assert l[[]] == "empty"

Order does not matter for Dict. It also cannot have duplicate elements. In this respect, Dict is similar to Set. You could say that a Dict is a Set with values.

{"Alice": 145, "Bob": 214, "Charlie": 301} == {"Alice": 145, "Charlie": 301, "Bob": 214}

When generating a dict from a dict literal, it is checked for duplicate keys. Any duplicates will result in a compile error.

{"Alice": 145, "Alice": 1} # KeyError: Duplicate key "Alice"

Empty Dict is created with {:}. Note that {} denotes an empty set.

mut_dict = !{:}
mut_dict.insert! "Alice", 145
mut_dict.insert! "Bob", 214
assert mut_dict["Alice"] == 145

Heterogeneous Dict

There need not be a single key/value type. Such a dictionary is called a _heterogenous dict.

d: {Str: Int, Int: Str} = {"a": 1, 1: "a"}
assert d["a"] == 1
assert d[1] == "a"

However, it is not possible to assign values of the same type to keys of different types, or values of different types to keys of the same type. In such cases, use the type Or instead.

invalid1 = {1: "a", "a": "b"}
invalid2 = {1: "a", 2: 2}

# Erg type inference does not infer Or type, so type specification is required
valid1: {Int or Str: Str} = {1: "a", "a": "b"}
valid2: {Int: Int or Str} = {1: "a", 2: 2}

Use with type ascription

The format x: y in {} is preferentially interpreted as a dictionary key/value pair. If you want to use it as a type ascription, you must enclose it in ().

x = "a"
{(x: Str): 1}