解析器若写 die unless $message,会拒绝空消息,也会拒绝文本 0;但本系列 TSV 允许空消息。perldata 的 Scalar values 指出:undef、空串和零在布尔判断里都为假;前者还可以用 defined 单独区分。字段是否存在,不能靠真假值来推断。

执行 perl examples/perl-language/experiments/04-values.pl,五种值按 undef、''、'0'、0、'queued' 排列。STDOUT 为:

1
2
3
4
5
6
0:defined=0,truth=0
1:defined=1,truth=0
2:defined=1,truth=0
3:defined=1,truth=0
4:defined=1,truth=1
empty-message-accepted

STDERR 空、退出码 0。用 defined 只检查是否提供值,不限制内容;如果业务要求消息非空,还须另加 length 条件。本系列的 demo.tsv 第三行有第四列,却在该列放空串:split /\t/, $line, -1 特意保留尾部空字段,所以 import 是 3、report 仍将该行计入 INFO。反例 invalid.tsv 的 DEBUG 被拒绝;它是枚举值越界,不是“空消息错误”。

误把警告当成校验会继续放行。perl -we 'use strict; use warnings; my $value = undef; print $value + 1;' 在 STDERR 警告未初始化值、STDOUT 输出 1,退出码仍为 0;这不能成为缺字段时补零的业务规则。真实解析器先用 @fields == 4 拒绝缺失的第四列,再允许确实存在的空串。当前解析的时间只检查字面格式;仍不承诺它代表有效日期。

补充实验没有改变这一结论,而是给真假判断增加比较边界。course-semantics.pl filter_forms 中的记录带有 duration_ms => 12 与 duration_ms => 40;闭包过滤器以后用数字比较判断 min_duration_ms,等级仍用字符串 eq。这避免把 0、''、undef 的布尔结果混入业务判断:是否提供字段用 defined,是否为空文本用 length,是否达到阈值用数值比较,是否等于等级枚举用字符串比较。

比较运算符也不能混用。$level eq 'WARN' 是字符串枚举判断;$duration_ms >= 100 是数值阈值判断;写成 $level == 'INFO' 会把两个非数字字符串数值化后当作 0 比较,course-semantics.pl comparison 固定输出 string_eq=1 numeric_eq=1,说明这个错误可能“碰巧为真”。短路默认值也要显式区分:$duration || 99 会把合法 0 改成 99,defined($duration) ? $duration : 99 才保留 0。优先级用括号写清:缺 duration 但 level 为 INFO 时,defined($d) && ($d == 0 || $level eq 'INFO') 为 0;少括号的 defined($d) && $d == 0 || $level eq 'INFO' 为 1。

课程 CLI 的 --min-duration 先拒绝 00、负数和非数字,再把合法值作为 min_duration_ms 交给过滤器;这条链路由 course-core.t、course-cli.t 和 course-semantics.t 覆盖,不能只靠 Perl 的真假规则兜底。

短路也只能表达已经写清的条件。defined($message) && length($message) 会在缺字段时跳过长度检查,但它仍会拒绝合法空消息;defined($duration) && $duration >= 100 适合数字阈值,却不说明字段是不是来自正确列。官方 perldata 只给真假值和上下文规则,业务上允许空消息、拒绝未知等级、接受持续时间 0,都必须由课程代码和测试单独记录。

练习:对第四列是字符 0 的合法记录,if ($message) 和 defined($message) 各是什么?前者假,后者真。若第四列根本不存在,则按字段数拒绝;即便两种情况都使某个布尔检查为假,也不能视作同一错误。证据、金标、正反例断言见 examples/perl-language/evidence/01-04.md。

参考:Perl 5.38.2 pod/perldata.pod(Scalar values、List value constructors)、pod/perlfunc.pod(defined、split);实验环境与校验见 examples/perl-language/VERSIONS.md。