ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Roc 语言嵌套 for 循环实战:基于 REPL 快照测试解析迭代、变量重赋值与作用域

Roc 语言嵌套 for 循环实战:基于 REPL 快照测试解析迭代、变量重赋值与作用域 【免费下载链接】rocA fast, friendly, functional language.项目地址https://gitcode.com/GitHub_Trending/ro/roc点击查看免费下载本指南以 Roc 仓库中 REPL 快照测试 for_loop_nested.md 为核心深入讲解 Roc 语言中嵌套for循环的完整语义如何遍历列表与 Range、如何在循环体内使用var变量累积结果、嵌套循环的求值顺序以及与break、模式匹配、iter_rev等特性的组合用法。读完本文你将能够读懂并用 REPL 亲手验证 Roc 的循环行为理解循环体只含语句、整个循环求值为{}这一核心设计并掌握将循环结果封装进块表达式对外返回的实战模式。一、从快照测试说起嵌套 for 循环的最小完整示例仓库 test/snapshots/repl/for_loop_nested.md 是一份 REPL 快照测试snapshot test它由四个部分构成# META测试元信息descriptionNested for loops说明了用例主题typerepl表明这是 REPL交互式求值类型的测试# SOURCE输入 REPL 的 Roc 源码»是 REPL 的输入提示符# OUTPUT期望的 REPL 输出此处为assigned \product# PROBLEMS期望的编译诊断NIL表示这段代码没有任何错误。该用例的完整源码如下与 test/snapshots/repl/for_loop_nested.md 一致» product { var result_ 0 for i in [1, 2, 3] { for j in [10, 20] { result_ result_ (i * j) } } result_ }这段代码表达了一个清晰的意图外层循环遍历[1, 2, 3]内层循环遍历[10, 20]累加所有i * j的乘积最终把结果绑定到product。也就是说1*10 1*20 2*10 2*20 3*10 3*20 180REPL 输出assigned \product表示绑定成功、编译与求值均无错误PROBLEMS: NIL。这正是嵌套for 循环最典型的使用场景对两个或多个列表做笛卡尔积式的遍历并在循环过程中累积状态。二、for 循环的核心语义遍历迭代器循环体只含语句根据语言参考 docs/langref/loops.mdRoc 的for循环用于“对迭代器iterator中的每个元素运行同一段代码”。语言参考给出的最简形态是var $sum 0 for n in 1..5 { $sum $sum n }这里有两点必须理解遍历的对象是迭代器1..5是一个 Range范围描述从 1 到 4不含 5的整数序列1..5则包含 5。如果边界是I64则得到Range(I64)其迭代器逐个产出I64值。for会反复调用迭代器的next方法直到耗尽。循环体只包含语句statements没有最终表达式这意味着循环体里不能像函数体那样“最后一行作为返回值”。整个循环表达式本身求值为{}单元值。循环的意义不在于返回什么而在于执行过程中的副作用——尤其是对var变量的重赋值或者调用有副作用的函数见 docs/langref/loops.md 与 docs/langref/functions.md 中关于 effectful functions 的说明。正是因为“循环求值为{}”for_loop_nested.md才会把循环包进一个块表达式{ ... }里让块的最后一行result_作为块的值返回。这是一种在纯函数式语言中“把命令式循环的结果导出出来”的标准手法值得反复体会。三、对列表使用 forList.iter 与迭代器协议for不仅能遍历 Range还能遍历任何实现了iter方法的类型只要该方法返回一个Iter。标准库的 List 就提供了List.iter因此可以直接对列表字面量使用forvar $sum 0 for n in [1, 2, 3, 4] { $sum $sum n }语言参考明确指出这段代码与前面1..5的版本“工作方式完全相同”Range 保存边界循环调用它的iter方法生成迭代器列表的iter方法同样生成一个产出相同元素的迭代器。循环随后反复对该Iter调用next。仓库中还有大量 REPL 快照测试可以佐证列表 for 循环的各类边界情况for_loop_list_u64.md遍历[1, 2, 3, 4, 5]累加求和for_loop_list_str.md 与 for_loop_list_bool.md对字符串、布尔值列表的遍历for_loop_empty_list.md遍历空列表[]时循环体一次都不执行value_保持初值42最终返回42——这说明空列表场景下var变量的初值直接成为结果fibonacci.md用循环实现斐波那契数列展示基于var迭代推进的典型写法。这些快照共同验证了一个事实for是 Roc 中“用语句式循环 变量重赋值”处理集合的标准入口。四、嵌套 for 循环求值顺序与累加器模式回到核心用例。嵌套循环的求值顺序与大多数语言一致外层取一个元素内层完整遍历一遍如此往复先外层i1内层完整走完j10, j20再i2……。result_作为跨迭代、跨层共享的累加器在内层循环里不断累积for i in [1, 2, 3] { for j in [10, 20] { result_ result_ (i * j) } }关于嵌套循环中的控制流语言参考在break一节给出了严格规定break只退出最内层循环见 docs/langref/loops.mdvar $result 0 for i in [1, 2, 3] { for j in [10, 20, 30] { if j 20 { break # 只退出内层循环外层继续 } $result $result j } }这意味着如果你想“提前终止整个嵌套结构”需要在每一层分别安排break条件或改用可空标记等模式判断是否继续。仓库中还有两个与嵌套/复杂循环密切相关的快照测试list_fold_sum_nested.md用List.fold实现嵌套求和可作为“函数式折叠 vs 语句式嵌套循环”两种风格的对照list_sublist_nested.md处理嵌套列表结构。五、循环体内的变量重赋值var、块作用域与条件更新嵌套循环能累积结果前提是var变量的重赋值机制。在for_loop_nested.md中result_被声明为var因此可以在内层循环体中反复重赋值。Roc 语言参考在 docs/langref/statements.md 的 reassignment 一节说明只有声明为var的局部变量才可以被重赋值循环是重赋值最典型的应用场景之一docs/langref/loops.md。值得注意的是快照用例中变量名带尾缀下划线result_、total_、sum_、max_。从 for_loop_var_reassign_tracking.md 的命名可以推断这是快照测试中为了清晰区分“需要追踪其跨迭代重赋值的变量”而采用的约定并非语言语法要求。循环体内也可以使用if做条件更新这在 for_loop_complex_mutation.md 中有完整展示——它统计 1 到 10 之间的偶数个数并累加偶数之和最后返回count_ * sum_» countEvens { var count_ 0 var sum_ 0 for n in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { if n % 2 0 { count_ count_ 1 sum_ sum_ n } else { {} } } count_ * sum_ }注意if的else分支写作{}因为if是表达式两个分支必须类型一致而{}是单元值这里我们只关心分支内的重赋值副作用不关心分支的值。这是一个非常实用且容易踩坑的细节。六、模式匹配、反向遍历与 whilefor 的进阶组合for的循环变量位置实际上是一个模式pattern因此可以内联解构详见 docs/langref/pattern-matching.md 与 docs/langref/loops.mdvar $total 0 for (x, y) in [(1, 2), (3, 4), (5, 6)] { $total $total x y } var $count 0 for _ in items { $count $count 1 }与赋值语句一样for的模式必须是穷尽的exhaustive。语言参考同时注明目前for模式的专用穷尽性错误尚未实现非穷尽的 tag 模式会被报为类型不匹配而类型检查器无法排除的非穷尽模式如数字字面量模式不会在编译期被捕获会在运行时崩溃。若想从后往前遍历列表可使用List.iter_revdocs/langref/loops.mdvar $visited [] for n in [1, 2, 3, 4].iter_rev() { $visited $visited.append(n) } # $visited 现在是 [4, 3, 2, 1]它就地反向读取列表不会像List.rev那样先构建一份反转副本字典和集合也提供iter_rev以反向遍历当前迭代顺序。对于其他迭代器来源可先用List.from_iter收集成列表再调用iter_rev。条件循环则由while承担——只要条件为真就重复执行循环体条件必须是布尔值var $i 0 var $sum 0 while $i 5 { $sum $sum $i $i $i 1 }七、如何在 REPL 中亲手验证快照测试的typerepl表明这些用例直接面向 Roc 的交互式 REPL。你可以通过以下方式亲自验证按照 BUILDING_FROM_SOURCE.md 或官方安装指南构建/安装roc在终端启动 REPL通常直接运行roc repl逐行输入 for_loop_nested.md 中的代码块观察是否输出assigned \product输入product查看其值验证是否得到180修改内层列表为[10, 20, 30]观察break对结果的影响确认break只作用于内层循环。对 REPL 输出格式更全面的参考可以查看 repl_basic_example.md展示多行输入与---分隔的多个输出以及 single_assignment.md展示普通不可重赋值变量的绑定。关于 REPL 中数字类型推断的行为可参考 repl_numeric_types.md 与 repl_bound_numbers_show_type.md。八、小结一段代码看懂 Roc 循环设计哲学回到开篇的快照测试把它的每个要素对应到语言机制上代码片段对应的语言机制var result_ 0var声明可变变量循环重赋值的前提docs/langref/statements.mdfor i in [1, 2, 3]对列表迭代底层调用List.iter生成Iter并反复nextdocs/langref/loops.mdfor j in [10, 20]嵌套循环内层对外层每个元素完整遍历一遍result_ result_ (i * j)循环体内的重赋值语句构成跨层累加器{ ... result_ }块表达式把循环副作用的结果导出为块的值assigned \product/PROBLEMS: NILREPL 绑定成功、无编译错误Roc 作为一门“快速、友好、函数式”的语言项目描述见 README.md用forvar提供了命令式循环的便利同时用“循环求值为{}”“循环体只含语句”的设计保持了表达式的清晰边界。理解嵌套 for 循环就等于理解了 Roc 中语句式编程与表达式化块之间最关键的衔接点——这是从 REPL 玩具走向真实集合处理程序的第一步。赞分享【免费下载链接】rocA fast, friendly, functional language.项目地址https://gitcode.com/GitHub_Trending/ro/roc点击查看免费下载相关推荐Roc 语言 for 循环中 var 变量逐次迭代重赋值基于 REPL 快照测试的完整解析Roc 语言 for 循环中 var 变量逐次迭代重赋值基于 REPL 快照测试的完整解析 导读 本文以 Roc 编译器仓库中的 REPL 快照测试 testRoc 语言 REPL 快照测试实战用 for 循环 var 变量跨迭代重赋值追踪验证编译器行为Roc 语言 REPL 快照测试实战用 for 循环 var 变量跨迭代重赋值追踪验证编译器行为 本篇技术指南以 Roc 编译器仓库项目描述为 A fasRoc 语言 for 循环与空列表迭代语义基于 REPL 快照测试的源码级解析Roc 语言 for 循环与空列表迭代语义基于 REPL 快照测试的源码级解析 本篇技术指南以 Roc 编译器仓库中的 REPL 快照测试 test/snap创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表