如何编写以描述为首个参数、代码块为第二个参数的Perl函数?
Perl实现
verify "描述" { 断言代码块 }语法的方案 可以实现你想要的功能,但Perl核心语法本身不支持这种参数顺序的语法解析,需要借助关键字扩展模块,或者使用折中方案。
为什么之前的尝试失败
- 原型
($&)无效:Perl的语法规则里,只有当代码块是第一个参数时,{}才会被解析为匿名子程序;如果是后续参数,Perl默认把{}识别为匿名哈希引用,因此触发类型错误。 - 柯里化方案报错:Perl无法识别
verify "描述" { ... }的语法结构,解析时会把{ ... }当成哈希,而非传递给柯里化返回的子程序,导致语法错误。
推荐方案:使用关键字扩展模块
借助Keyword::Simple模块可以自定义verify的语法解析逻辑,让Perl正确识别后续的{}为代码块。
示例代码
use Keyword::Simple; # 自定义verify关键字的解析逻辑 Keyword::Simple::define 'verify', sub { my $source_ref = shift; # 跳过verify关键字及前后空白 $$source_ref =~ s/^\s*verify\s*//; # 提取双引号包裹的描述信息 $$source_ref =~ s/^"([^"]+)"\s*// or die "verify后需跟随双引号包裹的描述信息"; my $description = $1; # 提取代码块内容 $$source_ref =~ s/^\{([^}]+)\}// or die "描述后需跟随代码块"; my $code_block = $1; # 将原语法替换为实际函数调用 $$source_ref = "verify_internal('$description', sub { $code_block });" . $$source_ref; }; # 实际执行断言逻辑的函数 sub verify_internal { my ($desc, $code) = @_; if ($code->()) { print "✅ PASS: $desc\n"; } else { print "❌ FAIL: $desc\n"; } } # 调用示例,完全符合你想要的语法 verify "检查数字大于5" { 6 > 5 }; verify "检查字符串为空" { "" eq "" }; verify "检查数组长度" { scalar(@{[1,2,3]}) == 3 };
无模块折中方案
如果不想依赖第三方模块,可以使用重载实现接近的语法,只是需要添加一个箭头符号:
示例代码
sub verify { my $desc = shift; # 返回一个重载了&{}的对象 return bless { desc => $desc }, 'Verify::Wrapper'; } package Verify::Wrapper; use overload '&{}' => sub { my $self = shift; return sub { my $code = shift; if ($code->()) { print "✅ PASS: $self->{desc}\n"; } else { print "❌ FAIL: $self->{desc}\n"; } }; }; # 调用示例(需添加->) verify "检查数字大于5"->(sub { 6 > 5 }); verify "检查字符串非空"->(sub { "hello" ne "" });
内容的提问来源于stack exchange,提问作者John Arrowwood
相关产品推荐
相关产品推荐

