Perl重复继承下常量重定义与原型不匹配问题排查
问题:Perl自定义Enum常量重定义错误
致歉:因代码过于复杂无法提供最小复现示例,以下说明问题:
原有基于Perl多重复继承的系统运行正常,我尝试用自定义的Enum类型替换原有的常量集合实现的“枚举”。该Enum可像之前一样生成常量,还能记录常量名称字符串,支持名称与数值互转。
枚举定义与导出(Auth::VerifyStatus.pm)
在Auth::VerifyStatus.pm中通过以下代码创建枚举:
use Enum v1.0.0; use constant _VERIFY_STATI => Enum->new('VS_STAT', [qw(OK ERR_BAD ERR_INVALID)]);
生成的常量为基名与列表项的拼接,如VS_STAT_OK、VS_STAT_ERR_BAD等。该包支持导出常量与枚举,导出设置如下:
%EXPORT_TAGS = ( 'enums' => [qw(_VERIFY_STATI)], 'status_enum' => [_VERIFY_STATI->names()], );
其中names()方法返回Enum生成的常量名称列表。
重新导出常量(Auth::Verifier.pm)
另一包Auth::Verifier.pm中执行use Auth::VerifyStatus v1.7.0 qw(:status_enum);,并重新导出状态常量:
%EXPORT_TAGS = ( 'enums' => [qw(Auth::VerifyStatus::_VERIFY_STATI)], 'status_enum' => [map { 'Auth::VerifyStatus::' . $_ } Auth::VerifyStatus::_VERIFY_STATI->names()]);
(添加map是为了尝试解决问题时限定包名)
错误现象
调试时运行perl -MAuth::Verifier -de1,在Auth::Verifier的末尾1;之后出现错误:
... Auth::Verifier ONE Auth::Verifier::CODE(0x2224de0)(lib/Auth/Verifier.pm:261): 261: 1; DB<1> c Constant subroutine Auth::VerifyStatus::VS_STAT_OK redefined at -e line 0. main::BEGIN() called at -e line 0 eval {...} called at -e line 0 Prototype mismatch: sub Auth::VerifyStatus::VS_STAT_OK () vs none at -e line 0. main::BEGIN() called at -e line 0 eval {...} called at -e line 0 ...
(“ONE”是为调试添加在1;前的输出)
Exporter执行时机
两个包的Exporter均在BEGIN块中执行,示例如下:
our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, @ISA, $VERSION); BEGIN { use Exporter qw(import); $VERSION = v1.7.0; $DB::single = 1; # trying to debug this @ISA = qw(Flags); %EXPORT_TAGS = ( ...
疑问
我完全不知道如何合理调试(错误均指向line 0),也不知如何修复,是否对Perl要求过高,应改用真正的OO语言?
额外参考:常量创建代码
以下是运行时创建常量的代码,供参考:
# query or add symbol table entry sub _sym($;$) { my ($name, $val) = @_; no strict 'refs'; unless ($#_ > 0) { if (my ($pkg, $sym) = $name =~ /^(.*::)(.+)$/) { return ${$pkg}{$sym}; } confess "_sym: invalid $name\n"; } *{$name} = $val; } # query or add symbol table entry to package sub _pkg_sym($$;$) { my ($pkg, $name, $val) = @_; unless ($#_ > 1) { _sym($pkg . '::' . $name); } else { _sym($pkg . '::' . $name, $val); } } # add constant sub _add_const($$$) { my $v = $_[2]; # constant value unless (_pkg_sym($_[0], $_[1])) { _pkg_sym($_[0], $_[1], sub () { $v }); } else { carp "_add_const: $_[1] already defined in $_[0]\n"; } }
内容的提问来源于stack exchange,提问作者U. Windl
相关产品推荐
相关产品推荐

