【问题标题】:Using Perl, how do I track where constants are being redefined?使用 Perl,我如何跟踪重新定义常量的位置?
【发布时间】:2016-04-21 03:54:37
【问题描述】:

我正在使用 perl。我不断收到这些错误

Constant subroutine Samp::foo redefined at /usr/local/share/perl/5.20.2/constant.pm
Constant subroutine Samp::bar redefined at /usr/local/share/perl/5.20.2/constant.pm 
Constant subroutine Samp::baz redefined at /usr/local/share/perl/5.20.2/constant.pm

我如何追踪重新定义它们的原因。使用蛮力方法,我可以通过将复合语句从use base qw/quz qaz/ 删除到use base 'qaz' 来抑制这个错误。我认为这表明我正在发生其他一些错误。如果您知道如何添加此调试代码,我可以破解 constant.pm

如果有一个 Devel:: 模块可以帮助我,或者另一个工作流程来解决这个问题,也可以提供道具。

问题似乎是documented here

【问题讨论】:

    标签: perl compiler-warnings circular-dependency


    【解决方案1】:

    我建议使用Carp 库。

    这里是最小的例子:

    Foo.pm

    package Foo;
    
    use Exporter 'import';
    @EXPORT_OK = qw( abc );
    
    use constant abc => 123;
    1;
    

    foo.pl

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use Foo qw( abc );
    use Carp;
    $Carp::Verbose = 1;
    $Carp::CarpLevel = 2;
    $SIG{__WARN__} = sub { carp(@_) };
    
    print "Before redefine\n";
    eval "use constant abc => 456;";
    print "After redefine\n";
    

    perl foo.pl

    Before redefine
    Constant subroutine main::abc redefined at /usr/share/perl5/vendor_perl/constant.pm line 140.
    at (eval 1) line 1.
        main::BEGIN() called at (eval 1) line 1
        eval {...} called at (eval 1) line 1
        eval 'use constant abc => 456;' called at foo.pl line 13
    After redefine
    

    【讨论】:

      【解决方案2】:

      添加use Carp::Always;

      $ perl -we'
         use constant FOO => 1;
         use constant FOO => 1;
      '
      Constant subroutine main::FOO redefined at /usr/share/perl/5.14/constant.pm line 136.
      

      $ perl -MCarp::Always -we'
         use constant FOO => 1;
         use constant FOO => 1;
      '
      Constant subroutine main::FOO redefined at /usr/share/perl/5.14/constant.pm line 136
              constant::import('constant', 'FOO', 1) called at -e line 3
              main::BEGIN() called at -e line 3
              eval {...} called at -e line 3
      

      如果您想知道第一个声明发生的位置,您可以覆盖 constant::import

      perl -we'
         use Carp qw( cluck );
         BEGIN {
            require constant;
            my $old = \&constant::import;
            my $new = sub {
               if (ref($_[1])) {
                  cluck("$_ declared") for keys %{ $_[1] };
               } else {
                  cluck("$_[1] declared");
               }
               goto &$old;
            };
            no warnings qw( redefine );
            *constant::import = $new;
         }
      
         use constant FOO => 1;
         use constant FOO => 1;
      '
      FOO declared at -e line 10
              main::__ANON__('constant', 'FOO', 1) called at -e line 18
              main::BEGIN() called at -e line 18
              eval {...} called at -e line 18
      FOO declared at -e line 10
              main::__ANON__('constant', 'FOO', 1) called at -e line 19
              main::BEGIN() called at -e line 19
              eval {...} called at -e line 19
      Constant subroutine main::FOO redefined at /usr/share/perl/5.14/constant.pm line 136.
      

      【讨论】:

      • (有一个模块可以很容易地覆盖东西,包括使用caller的东西,例如import。我不记得它是什么了。)
      • Hook::LexWrap 可能吗?
      • @Slade,不,这不是我的想法。我不知道它是否会起作用,而且它的整个词汇方面在这里是不可取的。
      猜你喜欢
      • 2011-04-05
      • 2013-01-02
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多