Perl - Subroutine redefined

后端 未结 9 1768
别那么骄傲
别那么骄傲 2020-12-14 16:19

I have asked this question before or searched and seen others ask - why am I getting the warning \"Subroutine mySub redefined at ../lib/Common.pm line x\"? and you

相关标签:
9条回答
  • 2020-12-14 17:06

    Take a look at the program package MyCommonPkg.pm and see what it says. Does it have something like this?

    package MyCommonPkg;
    
    use Exporter qw(import);   #  Might be "require" and not "use"
    our @EXPORT = qw(thisSubroutineIsNotDefinedAnywhereElse);
    

    The syntax may be a bit different. The main things you should see are the package statement, that it's using Exporter and that the @EXPORT array has your subroutine's name in it.

    What is going on is a namespace clash. Your package is defining the same subroutine you're defining.

    In order to prevent this from happening, Perl uses namespaces. By default, your namespace is main. However, packages are suppose to define their own separate namesakes using the package command.

    The full namespace of a subroutine or variable is the namespace followed by a double colon, followed by the subroutine or variable name. For example, of you look at File::Find, you will see references to the variables $File::Find::name and $File::Find::dir. These are the variables $name and $dir inside the File/Find.pm package under the File::Find namespace.

    In order to make things easier for you, packages can export their variables and subroutines into your main namespace. For example, if I use File::Copy, O can do this:

    ...
    use File::Copy
    ...
    copy ($file, $to_dir);
    

    Instead of:

    ...
    use File::Copy
    ...
    File::Copy::copy ($file, $to_dir);
    

    If you look at File/Copy.pm, you will see the following:

    package File::Copy;
    ...
    our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
    ...
    require Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(copy move);
    

    The package File::Copy; defines a namespace. The require Exporter; and the @ISA = qw(Exporter) allows the package to export subroutines and variables into the main namespace. The @EXPORT automatically, without it telling you anything, imports the copy and move subroutines into the main namespace whether you want them or not!

    That last bit is very important. It is now considered bad manners to use @EXPORT. Instead, you should use @EXPORT_OK which requires you to list the subroutines you want to use. More modern packages like Scalar::Util do this.

    So several things. First, does your MyCommonPkg have a package MyCommonPkg; statement. If not, it should. This keeps the packages subroutines and variables from affecting your program in nasty ways. Then, you can use @EXPORT or @EXPORT_OK.

    If MyCommonPkg does have a package statement, does it use @EXPORT? If so, you have several ways you can avoid this issue:

    • Ignore the warning. It's just a warning. Since you know you're redefining the subroutine, and you want to use your definition of the subroutine, ignore it.

    You can do this to turn off the warning as you redefine the subroutine:

    use MyCommonPkg;
    
    no warnings qw(redefine);
    sub thisSubroutineIsNotDefinedAnywhereElse {
       ...
    }
    use warnings qw(redefine);
    
    • Use require MyCommonPkg; instead of use MyCommonPkg;. This will prevent the importing of any subroutines or variables into your namespace including ones you wanted to use. Let's say MyCommonPkg defines four subroutines: thisSubroutineIsNotDefinedAnywhereElse, foo, bar, and barfoo. To use any of these subroutines.

    You need to do this:

    my $answer = MyCommonPkg::foo( $input );
    

    Not fun.

    • Use another name for your subroutine. It should have been documented that this subroutine is defined in MyCommonPkg, and if you want to use MyCommonPkg, you shouldn't use subroutine names that are exported.

    • Finally, if MyCommonPkg is fairly new, and isn't used in dozens of programs, use @EXPORT_OK instead of @EXPORT, and make sure all the programs that use MyCommonPkg are modified to export the subroutines they want:

    Like this:

    use MyCommonPkg qw(foo bar);
    

    In this case, only subroutines foo and bar are exported. The subroutines thisSubroutineIsNotDefinedAnywhereElse and barfoo are not exported into your environment.

    0 讨论(0)
  • 2020-12-14 17:12

    This sounds like a problem caused by circular dependencies. Here is how to track it down. If your problem class looks like this:

    package AlientPlanet;
    use Dinosaurs;
    sub has_dinosaurs {...}
    1;
    

    Then change your example to look like this:

    package AlienPlanet;
    sub has_dinosaurs {...}     # <-- swap
    use Dinosaurs;              # <-- swap
    1;
    

    Now compile your code with Carp::Always like this:

    ⚡ perl -MCarp::Always -c lib/AlienPlanet.pm                                                                                                            
    Subroutine has_dinosaurs redefined at lib/AlienPlanet.pm line 4.
        require AlienPlanet.pm called at lib/Dinosaurs.pm line 4
        Dinosaurs::BEGIN() called at lib/AlienPlanet.pm line 4
        eval {...} called at lib/AlienPlanet.pm line 4
        require Dinosaurs.pm called at lib/AlienPlanet.pm line 5
        AlienPlanet::BEGIN() called at lib/AlienPlanet.pm line 4
        eval {...} called at lib/AlienPlanet.pm line 4
    lib/AlienPlanet.pm syntax OK
    

    Now that you have a stacktrace you can see where the loop is. The quick and dirty solution is to use Class::Load in Dinosaurs.pm.

    For a more detailed explanation try my blog post.

    0 讨论(0)
  • 2020-12-14 17:13

    I had the same problem; It was because the program used a module and the subroutine was present both in the program and in the perl module;

    0 讨论(0)
提交回复
热议问题