Perl 14:稳定报表不能依赖哈希遍历顺序
四条已接受 Course 记录的等级分别包含 INFO、WARN、INFO、ERROR。计数放进哈希很自然,但键的遍历顺序不是报表协议。perldata 的 hash initializer 提醒:写入顺序不保证取出顺序。依赖 keys %counts 偶然排列出来的一次输出,会在另一个哈希种子、另一个进程或代码变更后使同一份数据产生不同报表。
当前 Course 入口不再走旧 LogTool::report,而是在 examples/perl-language/bin/logtool 的 report 命令中创建 LogTool::Course::Aggregator,调用 $aggregator->rows 取已经排序的行。tools/replay.pl --case all 对 fixtures/course.tsv 的完整链路断言报表字节必须等于:
1 | |
这个顺序与输入顺序无关:输入第一条是 INFO,第二条是 WARN,第四条是 ERROR;报表仍按等级名排序。course-engineering.t 还断言对象聚合器与函数聚合器等价、第二个聚合器实例不共享计数、rows 返回调用者拥有的副本。排序机制来自实现与这些断言,不来自某次哈希种子的幸运排列。
空结果还有一个细节:report 面对空 JSON Lines 会输出 TOTAL<TAB>0<LF>,不像 query 的无匹配结果可以是空 JSON Lines。两者是两个命令的不同契约。本章验证的是确定性文字和字节顺序,并没有声称报表目标文件遇到写入失败仍安全,也没有验证断电后的落盘保证。文件写入、rename、锁和故障矩阵由 32、38、39 继续限定。
练习:若有人把聚合器里的排序改成裸 keys %counts,一次成功运行能否证明报表仍确定?不能;比较金标可能抓到差异,但判断是否遵守协议要先审查排序是否被明确编码。复跑证据见 completion/evidence/semantics/*replay-all.*;参考 Perl 5.38.2 pod/perldata.pod(hash initializer)、pod/perlfunc.pod(keys 与 sort)。









