ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Roc 语言 REPL 字典下标查询:解读 `Dict.subscript` 快照测试与 `Err(KeyNotFound)` 语义

Roc 语言 REPL 字典下标查询:解读 `Dict.subscript` 快照测试与 `Err(KeyNotFound)` 语义 Roc 语言 REPL 字典下标查询解读Dict.subscript快照测试与Err(KeyNotFound)语义【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/rocRoc 语言内置字典类型Dict的下标操作subscript用于按键取值命中时返回Ok(value)键不存在时返回Err(KeyNotFound)。本文以仓库中的 REPL 快照测试 test/snapshots/repl/dict_subscript.md 为骨架逐行剖析其交互过程并结合 src/build/roc/Builtin.roc 的源码实现讲清subscript与Dict.get的别名关系、Try结果类型与KeyNotFound错误的由来以及这套快照文件如何作为可重复执行的回归测试运行。一、快照测试文档的结构META / SOURCE / OUTPUT / PROBLEMSdict_subscript.md采用 Roc 仓库 REPL 快照测试的统一四段式结构每一段用#标题分隔段落作用# METAini 格式的元信息声明description用例语义描述与typerepl测试类型为 REPL 交互# SOURCE以»提示符书写的 REPL 输入序列即测试执行的原始命令# OUTPUT每一条输入对应的预期输出用---分隔作为断言基准# PROBLEMS已知问题列表NIL表示当前无未解决的问题本用例的 META 描述精确概括了被测语义Dict.subscript returns the value for a key, or Err(KeyNotFound) for absent keysDict.subscript返回键对应的值键缺失时返回Err(KeyNotFound)。typerepl表明该快照由 REPL读取-求值-打印循环驱动# PROBLEMS为NIL说明该行为目前无已知缺陷属于稳定契约。二、逐行解读 SOURCE链式构造与下标查询快照的 SOURCE 段包含 4 条 REPL 命令» d Dict.empty().insert(alice, a heap allocated value).insert(bob, another heap value) » d.subscript(alice) » d.subscript(missing) » d.subscript(bob) » d.len()1. 链式构造字典d第一行演示了Dict的声明式构造风格以Dict.empty()创建空字典再通过两次.insert(key, value)链式插入两个键值对alice→a heap allocated valuebob→another heap value值特意选用了堆分配的字符串heap allocated value说明subscript返回的是对存储值的访问结果涉及引用计数与所有权语义而非仅限于栈上可拷贝的标量。REPL 对此行的回显为assigned \d表示变量绑定成功。2. 命中键Ok(value)» d.subscript(alice)输出为Ok(a heap allocated value)说明字典中存在键alice时subscript返回包装在Ok中的值——Roc 用Try结果类型表达可能失败的操作成功分支为Ok。3. 缺失键Err(KeyNotFound)» d.subscript(missing)输出为Err(KeyNotFound)这是本用例的核心断言查询不存在的键不会崩溃、不会返回空值而是以类型安全的方式返回错误标签KeyNotFound交由调用方通过模式匹配处理。4. 再次验证第二个键» d.subscript(bob)输出Ok(another heap value)证明字典中多个条目均可被正确索引查询逻辑与插入顺序、具体键名无关。5. 长度校验» d.len()输出2与插入的两个键值对数量一致用于佐证字典状态的完整性——插入了 2 条即长度为 2。三、源码级印证subscript是Dict.get的别名在 src/build/roc/Builtin.roc 中可以看到subscript的完整定义## Alias for [Dict.get], enabling the future dict[key] subscript operator. ## Returns the value for a given key. ## ## Returns Err KeyNotFound if the dictionary has no value for the key. ## roc ## expect Dict.empty() ## .insert(Apples, 12.U64) ## .subscript(Apples) Ok(12) ## expect Dict.empty() ## .insert(Apples, 12.U64) ## .subscript(Oranges) Err(KeyNotFound) ## subscript : Dict(k, v), k - Try(v, [KeyNotFound, ..]) where [k.is_eq : k, k - Bool, k.to_hash : k, Hasher - Hasher] subscript |dict, key| Dict.get(dict, key)几个关键信息纯别名实现subscript |dict, key| Dict.get(dict, key)没有任何额外逻辑语义完全等同Dict.get。返回值类型Try(v, [KeyNotFound, ..])——成功时是Ok(value)失败时是Err(KeyNotFound)其中[KeyNotFound, ..]是开放标签联合允许错误集合在调用链上继续扩展。键的类型约束where [k.is_eq : k, k - Bool, k.to_hash : k, Hasher - Hasher]要求键类型k提供相等比较is_eq与哈希to_hash能力这正是字典查找的数据结构基础。设计意图文档注释明确说明这是为未来dict[key]下标运算符语法预留的别名。当前阶段先以函数形式提供稳定 API后续语法糖可直接映射到该函数。而Dict.get的底层实现位于同文件 src/build/roc/Builtin.rocget : Dict(k, v), k - Try(v, [KeyNotFound, ..]) where [k.is_eq : k, k - Bool, k.to_hash : k, Hasher - Hasher] get |dict, key| match dict { HashMap(data) match dict_find(data, key) { Found(found) Try.Ok(found.value) Missing(_) Try.Err(KeyNotFound) } }实现揭示了Dict的真实形态它是对HashMap的封装模式匹配HashMap(data)内部通过dict_find在哈希表中定位键返回Found(found)时取出found.value包成Try.Ok返回Missing(_)时构造Try.Err(KeyNotFound)。这与快照中Ok(...)/Err(KeyNotFound)的输出完全一一对应。从源码结构可以推断字典查找的时间复杂度取决于内部哈希表的实现is_eq与to_hash约束保证任意合法键类型都能走统一的查找路径。四、错误处理的实战模式匹配Try结果subscript返回Try(v, [KeyNotFound, ..])意味着调用方必须显式处理缺失键的情况Roc 编译器会强制穷尽匹配。常见写法result Dict.empty().insert(alice, 1).subscript(bob) # 显式匹配两个分支 when result is Ok(value) - value Err(KeyNotFound) - 0 # 提供默认值KeyNotFound是与Dict深度绑定的语义化错误标签它比返回OptionNone携带更明确的意图——这个键不在字典里并且由于错误集合是开放的[KeyNotFound, ..]Try可以与Result风格的其他错误标签自由组合形成统一错误链。五、相关快照同一语义矩阵的更多侧面dict_subscript.md并非孤例仓库test/snapshots/repl/目录下存在一组围绕Dict键查找语义的姊妹快照共同构成覆盖矩阵test/snapshots/repl/dict_get_missing.md专门验证Dict.get对缺失键返回Err(KeyNotFound)的基准行为test/snapshots/repl/dict_from_iter.md 与 test/snapshots/repl/dict_from_list_duplicates.md覆盖从迭代器/列表构造字典及重复键的处理test/snapshots/repl/dict_collision_cluster.md 与 test/snapshots/repl/dict_collision_rebuild.md验证哈希碰撞场景下的查找正确性test/snapshots/repl/dict_growth_all_lookups.md字典扩容后所有键仍可查询test/snapshots/repl/dict_keep_if.md过滤操作后的键查找。这些用例说明subscript/get的Ok/Err(KeyNotFound)契约在插入、重复、碰撞、扩容、过滤等各类字典状态变迁下均保持稳定。六、横向对比subscript在不同容器中的语义差异subscript并不是Dict的专属 APIsrc/build/roc/Builtin.roc 中不同容器类型各自定义了符合自身语义的subscript容器签名返回语义Dictsubscript : Dict(k, v), k - Try(v, [KeyNotFound, ..])按键取值缺失返回Err(KeyNotFound)Listsubscript : List(item), U64 - Try(item, [OutOfBounds, ..])Builtin.roc按下标取元素越界返回Err(OutOfBounds)是List.get的别名Setsubscript : Set(item), item - BoolBuiltin.roc判断成员是否存在是Set.contains的别名可以看出subscript是 Roc 内建容器统一暴露的索引访问接口名而具体返回类型随容器语义而变Dict返回Try结果、List返回带越界错误的Try结果、Set直接返回布尔值。理解这一设计有助于在阅读和编写 Roc 代码时快速把握不同容器的访问契约。七、如何亲自复现该快照该快照文件本身是测试资产读者可以在仓库中查看也可以在自己环境中运行 REPL 验证相同行为# 在仓库根目录构建或使用已安装的 roc 二进制然后启动 REPL roc repl进入 REPL 后逐条输入 SOURCE 段的命令去掉»提示符观察输出是否与 OUTPUT 段一致。若roc已安装且版本与仓库匹配d.subscript(alice)应回显Ok(a heap allocated value)d.subscript(missing)应回显Err(KeyNotFound)d.len()应回显2。该快照在 CI 中作为回归测试持续执行任何破坏Dict.subscript契约的改动都会导致输出比对失败从而守护这套语义的长期稳定。八、小结dict_subscript.md用 5 条 REPL 命令完整锁定了Dict.subscript的行为契约命中返回Ok(value)、缺失返回Err(KeyNotFound)、字典长度不受查询影响。源码侧src/build/roc/Builtin.roc 表明subscript是Dict.get的纯别名底层经dict_find在HashMap中查找并区分Found/Missing两种结果类型签名Try(v, [KeyNotFound, ..])与is_eq/to_hash约束共同保证了类型安全与可扩展的错误处理。这套快照文档 内建库源码的组合既是可复现的测试用例也是理解 Roc 字典查找语义与未来dict[key]语法糖的最短路径。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表