# 映射 映射是 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 }
给定带标签映射时,`assoc`、`dissoc` 和 `merge` 会保留标签: `[assoc $point :z 30]` 仍然是 `%Point`。 ## 另见 - 集合 — 字面量、持久化、`from-entries` - 模式匹配 — 带标签映射解构 - 列表 — `zip`、`from-entries`、按位置访问 - 集合 — 集合形态的集合