thp-web/md/learn/data-structures/maps.md

116 lines
2.3 KiB
Markdown
Raw Normal View History

2023-10-02 01:41:38 +00:00
# Maps
2024-03-13 17:16:29 +00:00
Also known as Associative Arrays, or Objects in other languages.
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
All maps must have a definition, which define their fields and datatypes.
There can also be anonymous maps, which may contain any key.
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
## Named Maps
2023-10-02 01:41:38 +00:00
```thp
2024-03-13 17:16:29 +00:00
// Here we define a map, called Person
map Person {
String name,
String surname,
Int age,
}
// Here we declare an instance of a Person.
val john_doe = Person {
2023-10-02 01:41:38 +00:00
name: "John",
surname: "Doe",
age: 33,
}
2024-03-13 17:16:29 +00:00
// If the compiler can infer the type of a Map,
// we can omit its type
var Person mary_jane = .{
name: "Mary",
surname: "Jane",
age: 27,
}
```
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
To access the fields of a map we use square braces `[]`.
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
```thp
2024-03-16 14:30:32 +00:00
mary_jane["age"] += 1
print(mary_jane["name"]) // Mary
2023-10-02 01:41:38 +00:00
```
2024-03-16 14:30:32 +00:00
Or dot access `.` if the field's name is a valid identifier.
```thp
mary_jane.age += 1
print(mary_jane.name)
```
2024-03-13 17:16:29 +00:00
## Anonymous maps
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
An anonymous map allows us to store and retrieve any key of any datatype.
They are declared as `Map`.
2023-10-02 01:41:38 +00:00
```thp
2024-03-13 17:16:29 +00:00
val car = Map {
brand: "Toyota",
model: "Corolla",
year: 2012,
2023-10-02 01:41:38 +00:00
}
2024-03-13 17:16:29 +00:00
```
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
Anonymous maps can also can have their type omitted.
2023-10-02 01:41:38 +00:00
2024-03-13 17:16:29 +00:00
```thp
var car = .{
brand: "Toyota",
model: "Corolla",
year: 2012,
2023-10-02 01:41:38 +00:00
}
```
2024-03-13 17:16:29 +00:00
If the compiler encounters a map without a type (that is, `.{}`)
and doesn't expect a specific type, it will assume it is an
anonymous map.
We can freely assign fields to an anonymous map:
```thp
// Modify an existing field
2024-03-16 14:30:32 +00:00
car["year"] = 2015
2024-03-13 17:16:29 +00:00
// Create a new field
2024-03-16 14:30:32 +00:00
car["status"] = "used"
2024-03-13 17:16:29 +00:00
```
2023-10-02 01:41:38 +00:00
2024-03-16 14:30:32 +00:00
However, if we try to access a field of an anonymous map we'll get
a nullable type, and we must annotate it.
2024-03-13 17:16:29 +00:00
```thp
2024-03-16 14:30:32 +00:00
// This is ok, we are declaring what datatype we expect
String? car_status = car["status"]
// This won't work, the compiler doesn't know what datatype to use
var car_status = car["status"]
2024-03-13 17:16:29 +00:00
```
2024-03-16 14:30:32 +00:00
Instead, we can use the `get` function of the map, which expects a
datatype and returns that type as nullable
2024-03-13 17:16:29 +00:00
```thp
2024-03-16 14:30:32 +00:00
val car_status = car.get[String]("status")
2024-03-13 17:16:29 +00:00
```
2023-10-02 01:41:38 +00:00
2024-03-16 14:30:32 +00:00
Both ways to get a value will check that the key exists in the map,
2024-03-13 17:16:29 +00:00
and that it has the correct datatype. If either the key doesn't exist
2024-03-16 14:30:32 +00:00
or it has a different datatype, it will return `null`.
We can also use dynamic keys, following the same rules:
2023-10-02 01:41:38 +00:00
2024-03-16 14:30:32 +00:00
```thp
val generated_value = "key"
String? v = map[generated_value]
// or
val v = map[String](generated_value)
```