ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Roc 语言 for 循环遍历 List Str 实战:从 REPL 快照测试到语言参考的完整解读

Roc 语言 for 循环遍历 List Str 实战:从 REPL 快照测试到语言参考的完整解读 Roc 语言 for 循环遍历 List Str 实战从 REPL 快照测试到语言参考的完整解读【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/rocRoc 是一门快速、友好、函数式的系统编程语言本仓库即其编译器实现。本文以仓库内 REPL 快照测试 test/snapshots/repl/for_loop_list_str.md 为切入点完整剖析 Roc 中for循环遍历List Str字符串列表的语法、变量可变语义、块表达式求值规则并延伸到快照测试的 META/SOURCE/OUTPUT/PROBLEMS 四段式结构与底层生成逻辑。读完本文你将能够读懂任意一个 REPL 快照文件、在 REPL 中熟练编写基于for的累加循环并理解assigned \count 这类输出的产生原理。一、快照文件全景一个最小但完整的 for 循环用例关联文档test/snapshots/repl/for_loop_list_str.md全文如下这是理解本文所有内容的地基# META descriptionFor loop iterating over List Str typerepl» count { var counter_ 0 for _ in [hello, world, test] { counter_ counter_ 1 } counter_ }# OUTPUT assigned count # PROBLEMS NIL这个文件只有不到 30 行却完整覆盖了 Roc 编译管线的三个关键验证维度META 区声明该快照的descriptionFor loop iterating over List Str与typerepl告诉快照工具这是一个 REPL 类型的快照需走 REPL 求值路径而非普通编译路径SOURCE 区以»提示符模拟用户在 REPL 中的输入——一个块表达式块内先声明可变变量counter_再用for循环遍历三个字符串最后返回累加后的counter_OUTPUT / PROBLEMS 区断言 REPL 求值结果——变量count被成功赋值assigned \count且编译过程没有任何诊断报告NIL。从源码结构看这属于仓库中typerepl一族的“成功路径”快照PROBLEMS为NIL表示编译与求值全程零错误、零警告正好与 test/snapshots/README.md 中NILmeans the compile produced no reports的约定一致。二、逐行拆解 SOURCEfor 循环 可变变量 块表达式的组合2.1var counter_ 0可变变量声明Roc 默认不可变但for循环天然需要“跨迭代累积状态”因此 Roc 提供var关键字声明可变变量。这里的命名counter_带尾下划线是 REPL 快照中用于区分可变容器的常见命名风格——在 for_loop_list_bool.mdvar allTrue_ Bool.True、for_loop_var_conditional_persist.mdvar lastEven_ 0、var evenCount_ 0等兄弟快照中可以看到完全一致的模式。var声明的变量可在循环体内被重新赋值这正是 docs/langref/loops.md 所述Loops are typically used for variable reassignment的典型用法。2.2for _ in [hello, world, test]迭代器驱动 通配符模式Roc 的for循环不是 C 语言那种带索引的计数器循环而是迭代器驱动的遍历。根据 docs/langref/loops.mdfor的循环源可以是 range如1..5也可以是任何实现了iter方法且返回Iter的类型List实现了List.iter因此可以直接对列表做for n in [1, 2, 3, 4]循环会在每次迭代时对迭代器调用next逐项产出元素。这里遍历的是字符串列表[hello, world, test]即List Str——本快照的 description 正是由此而来。循环变量使用_通配符表示“我关心迭代次数但不关心元素本身”这与 docs/langref/loops.md 中的示例for _ in items { $count $count 1 }完全一致。由于for与in之间是一个 pattern元素可以被解构或忽略_正是不命名该模式的合法写法。2.3counter_ counter_ 1循环体内的副作用循环体是一个语句块内部执行可变变量重新赋值。每迭代一次counter_就自增 1。因为列表恰好有 3 个元素循环结束后counter_的值为 3。值得注意循环体只能包含语句没有最终表达式整个循环本身求值为{}空记录类型。所以想要从循环带出结果必须依赖外部可变变量——这正是本快照counter_变量的作用。2.4 块表达式求值count的最终值整个 SOURCE 是一个块表达式count { var counter_ 0 for _ in [hello, world, test] { counter_ counter_ 1 } counter_ }块内最后一条表达式counter_即块的求值结果值为 3再通过 REPL 的顶层赋值绑定到名称count。这就是 OUTPUT 区出现assigned \count的原因——REPL 确认了一个新定义count 的诞生其值为 3循环执行了 3 次自增。三、OUTPUT 的底层来源assigned \count 是怎么生成的快照工具对 REPL 输入的处理逻辑位于 src/snapshot_tool/main.zig。在 该文件的编译求值路径 中可以找到关键代码try session.upsertDefinition(allocator, identity.kind, identity.name, input); return try std.fmt.allocPrint(allocator, assigned {s}, .{identity.name});也就是说REPL 会话先通过upsertDefinition把新定义写入会话环境后续输入可以继续引用count随后格式化输出assigned \名字 作为该输入的 REPL 响应。这正是本快照 OUTPUT 区assigned \count的直接生成来源。与之呼应REPL 会话实现 [src/cli/ReplSession.zig](https://link.gitcode.com/i/f590b69eed02fe16f1bca3cb7178259b) 中也内嵌了大量同类断言如x 5→assigned x、count ...→assigned count从测试层面验证了这一输出协议。而在快照文件的约定层面test/snapshots/README.md 明确指出普通快照的PROBLEMS区包含诊断报告的 S 表达式序列化NIL表示编译没有产生任何报告。本文快照的PROBLEMS为NIL即for循环遍历List Str的这段代码通过了词法、语法、canonicalization、类型检查全流程且零报告。四、横向对照同一家族的 for 循环快照揭示了什么test/snapshots/repl/目录下存在一组完整的for_loop_*快照它们从不同角度锁定 for 循环的行为是理解本快照定位的最佳参照快照文件覆盖的行为点for_loop_list_bool.md遍历List Bool循环体内用if/else条件更新可变变量for_loop_list_u64.md遍历List U64数值列表for_loop_empty_list.md空列表场景验证零次迭代时可变变量保持初值for_loop_nested.md嵌套 for 循环for_loop_complex_mutation.md更复杂的可变变量变更场景for_loop_var_conditional_persist.md变量跨迭代持续存在且按条件奇偶判断更新for_loop_var_every_iteration.md每次迭代都更新的变量for_loop_var_reassign_tracking.md对可变变量重新赋值的跟踪从源码结构可以推断这些快照共同验证的正是编译器对循环 可变变量的控制流分析变量在每次迭代的读写必须被正确追踪循环结束后块表达式读到的是最新值。本快照for_loop_list_str.md在其中承担的角色是字符串元素类型维度上的最小回归保障——确认List Str的迭代协议与List U64、List Bool一致且_通配符模式不会破坏元素遍历。五、语言参考中的 for 循环全景结合 docs/langref/loops.md把本快照用到的 for 循环能力放到完整语言特性中还有几个关键扩展点值得掌握5.1 遍历 Range 与自定义迭代器除列表外for 可直接遍历 rangevar sum 0 for n in 1..5 { sum sum n }1..5是左闭右开区间不含 51..5则包含 5若边界是I64则得到Range(I64)其迭代器产出I64值。5.2 反向遍历需要从尾到头遍历时用List.iter_rev替代iter它就地反向读取不会像List.rev那样先构造一份反转副本var visited [] for n in [1, 2, 3, 4].iter_rev() { visited visited.append(n) } # visited 现在是 [4, 3, 2, 1]字典Dict和集合Set也提供iter_rev按当前迭代顺序反向遍历。5.3 模式匹配与解构for与in之间是完整模式可内联解构元组var total 0 for (x, y) in [(1, 2), (3, 4), (5, 6)] { total total x y }也可以嵌套模式_用于不命名。需要注意模式必须穷尽——如果模式可能无法匹配运行时的某个元素如for Ok(v) in items会触发穷尽性相关错误当前实现中该错误以类型不匹配形式报告无法被类型检查器排除的非常量模式如数字字面量模式甚至会在运行时崩溃因此官方建议无法写出穷尽模式时先用一个名字绑定整个元素再在循环体内用match处理。5.4break与whilebreak可立即退出最内层循环在嵌套循环中只跳出内层while则按布尔条件反复执行条件必须求值为布尔值。循环体仅含语句、无最终表达式、整体求值为{}的规则对两者同样适用。六、如何运行与验证快照工具使用指南本快照属于编译器仓库的自测资产可通过快照工具实际运行验证操作方式见 test/snapshots/README.md# 生成/运行全部快照 zig build run-snapshot-tool # 仅更新/运行指定快照文件 zig build run-snapshot-tool -- test/snapshots/repl/for_loop_list_str.md # 从 PROBLEMS 更新期望输出 zig build run-snapshot-tool -- test/snapshots/repl/for_loop_list_str.md --update-expected # 调试 REPL 求值过程仅适用于 typerepl 快照需单文件 zig build run-snapshot-tool -- test/snapshots/repl/for_loop_list_str.md --trace-eval--trace-eval标志会开启详细的解释器跟踪是调试 REPL 快照的利器它在 debug 构建中默认启用release 构建需附加-Dtrace-evaltrue。快照测试的价值在于以极小的代价锁定编译器每一阶段的输出——词法、语法、canonicalization、类型检查——一旦编译器行为意外变化对应快照立刻暴露回归。七、从快照到实战在 REPL 中写出可运行的 for 循环把快照的语法迁移到日常 REPL 或 .roc 源码中一个等价、可读性更好的计数循环是这样count { var counter_ 0 for _ in [hello, world, test] { counter_ counter_ 1 } counter_ }块表达式末尾的counter_是返回值这是循环结果带出的标准手法若关心元素本身把_换成具名模式即可如for word in words并在循环体内基于word做处理若需要条件更新参考 for_loop_list_bool.md 的if/else结构在循环体内对可变变量按条件赋值。理解这份快照等于同时掌握了三件事Rocfor循环的迭代器语义、var可变变量与块表达式的组合求值方式以及 REPL 快照测试输入-输出-诊断三段式断言的底层实现。对希望为 Roc 编译器贡献测试或深入 REPL 实现的人来说test/snapshots/repl/for_loop_list_str.md及其兄弟快照是一组小而完整的入门标本。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表