# 映射
映射是 Deft 的持久化哈希映射,写作 `%{ :key value ... }`,带标签
映射(`%Point{ :x 1 }`)是携带类型名的同一结构。这里的每个操作都
返回新映射,原映射保持不变。这些裸函数被编译进每个运行时,无需
导入。关于更广泛的集合模型和解构模式,参见
集合和
模式匹配。
## 函数
| 函数 | 用途 |
|---|---|
| `keys m` | 键组成的列表 |
| `values m` | 值组成的列表 |
| `entries m` | `@{ key value }` 对组成的列表 |
| `merge m1 m2` | 合并两个映射;后面的键胜出 |
| `get m key ?default` | 按键(映射)或按索引(列表)查找 |
| `assoc m k v ...` | 添加或覆盖一个或多个键 |
| `dissoc m k` | 移除一个键 |
| `tag m type-name` | 将普通映射包装为带标签的实例 |
| `untag m` | 去除标签,返回普通映射 |
| `assoc-in m path v` | 在嵌套路径上设置值 |
| `get-in m path ?default` | 在嵌套路径上查找值 |
`get` 自动把字符串键转换为关键字,所以 `[get $m "name"]` 和
`[get $m :name]` 结果一致。`merge` 恰好接受两个映射——再次应用它
即可合并更多。`assoc` 在映射之后接受任意数量的键值对,因此一次
调用可以设置多个键。
`keys`、`values` 和 `entries` 按插入顺序返回,对给定的操作序列
是确定性的,但并非排序。`entries` 是 `from-entries` 的逆操作:
[from-entries [entries $m]] # round-trips back to $m
`assoc-in` 和 `get-in` 的路径是从最外层到最内层读取的键向量。
`assoc-in` 要求每个中间层已经是映射;`get-in` 一旦某一层缺失,
就返回默认值(省略时为 `nil`)。
`tag` 接受 字符串 类型名并生成 `%Point{ ... }`;
`[type [tag $m "Point"]]` 返回 `"Point"`。`untag` 返回内部的普通
映射;对带标签映射进行模式匹配会同时解构标签和字段(参见
模式匹配)。
## 示例
def user %{ :name "Alice" :age 30 :role :admin } $user~name # => "Alice" — field access [get $user :name] # => "Alice" [get $user :email "n/a"] # => "n/a" — default $user # the original is unchanged
添加、更新和移除键:
[assoc $user :email "alice@example.com"] # add a key [assoc $user :age 31 :role :owner] # several pairs at once [dissoc $user :role] # remove a key [merge $user %{ :age 31 :city "Paris" }] # later map wins
迭代辅助函数返回列表:
[keys $user] # => @{ :name :age :role } [values $user] # => @{ "Alice" 30 :admin } [entries $user] # => @{ @{:name "Alice"} ... }
嵌套访问与更新:
def cfg %{ :db %{ :host "localhost" :port 5432 } } [get-in $cfg @{ :db :host }] # => "localhost" [get-in $cfg @{ :db :user } "root"] # => "root" — default [assoc-in $cfg @{ :db :port } 6543] # => port set to 6543 [assoc-in %{ :a %{} } @{ :a :b } 1] # => %{ :a %{ :b 1 } }
带标签映射携带类型名,行为与普通版本相同:
def point [tag %{ :x 10 :y 20 } "Point"] [type $point] # => "Point" $point~x # => 10 [untag $point] # => %{ :x 10 :y 20 }