Perl - Subroutine redefined
Asked Answered
M

9

33

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 always get the answer you declared the sub twice in the same code. I created this test package:

ENTIRE FILE ---------------

package MyCommonPkg;

use strict;

sub thisSubroutineIsNotDefinedAnywhereElse{
}

1;

ENTIRE FILE ---------------

and I USE this package from a perl script, which uses other packages, that use this package also, and I get the warning:

Subroutine ThisSubroutineIsNotDefinedAnywhereElse redefined at ../lib/MyCommonPkg.pm line 19.

I promise I did not declare this sub anywhere else. So is this caused by a circular reference? How can I go about tracking the cause of this warning down and fixing?

Monaural answered 6/8, 2010 at 22:33 Comment(3)
Do you really declare package Common.pm? That seems like an error.Ardel
Do you happen to have two packages with the same name? That can cause a namespace collision. Always name your packages for the file they are in (replacing / with ::, and stripping .pm). This can also happen if you have no namespace, which really means that you are in main.Joby
no - i didn't declare it Common.pm. I just renamed things to get a pseudo code example up and typoed. I'll edit.Monaural
J
40

Do you have a dependency loop? If Perl starts compiling your script and encounters a line like this:

use PackageA;

Perl pauses the compilation of your script; locates PackageA.pm and starts compiling it. If it encounters a line like this:

use PackageB;

Perl pauses the compilation of PackageA; locates PackageB.pm and starts compiling it. Normally, that would complete successfully, and Perl would go back to complete compiling PackageA and when that completes successfully it would go back to compiling your script and when that completes successfully it would start to execute the compiled opcodes.

However, if PackageB.pm contains this line:

use PackageA;

You might expect it would do nothing since Perl has already processed PackageA.pm but the problem is that it hasn't finished yet. So Perl will pause the compilation of PackageB and start compiling PackageA.pm again from the beginning. That could trigger the message you're seeing about subroutines in PackageA being redefined.

As a general rule, two packages should not both depend on each other. Sometimes however the loop is harder to locate because it is caused by a third package.

Junkman answered 7/8, 2010 at 5:37 Comment(1)
i think this is my problem - how to fix then? it's not a circular reference - i would see a circular reference as PackageA has "use PackageB;" and PackageB has "use PackageA;" Rather I have a script "main.pl" that uses PackageA and uses PackageB, and PackageA also uses PackageB. Shouldn't be anything wrong with that?Monaural
R
24

When you have two subroutines with the same name in different packages, you ought to see this warning (when warnings are enabled) as "Subroutine new redefined....". The simple reason (which is very close to what Grant McLean said, but still not exactly) is you must get your packages skip the compiling phase and make then require. This way, the Perl namespace manager will not find any such conflicting symbols with same name at compile time, and if you modules do not have any errors, they will work just fine afterwards also.

Just make sure you implement

require Module;

statement rather than

use Module;

You should not see this warning again.

Remembrancer answered 10/8, 2012 at 22:58 Comment(1)
It's fine to have subs with the same name in different packages. Perl won't warn about it - that's kinda the point of packages :)Carnelian
A
8

If you're on a system with a case-insensitive filesystem (Windows, and quite often OSX), and you do use Common in one file and use common in another, you can cause problems like this.

Anaxagoras answered 7/8, 2010 at 0:33 Comment(1)
searched for occurrences of this and could not find any. very good to know though - thanks!Monaural
G
7

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.

Gibbons answered 20/1, 2013 at 21:54 Comment(0)
H
2

Are you by any chance running this as a cgi-script on a web-server?

I find I need to restart the webserver to get around this warning.

Hallah answered 27/2, 2011 at 15:43 Comment(0)
P
1

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.

Pharmacognosy answered 27/10, 2013 at 17:4 Comment(0)
C
0

I tried to use "package Common.pm" as a package name. The compiler gave me errors. Very kind of it eh? What version of Perl are you using? I tried it on 5.10.0 and 5.12.1.

Even if you can compile it is good practice to remove the .pm file. For Example;

File: some_package.pm;

package some_package;
use strict;

sub yadayadayada { ... }

1;
Costar answered 7/8, 2010 at 1:51 Comment(0)
E
0

Make sure you didn't forget this line at the end of your module:

1;

I know it's been included in a few of the examples here, but I mention it because it is easy to overlook, and in my case it turned out to be the sole cause of the errors!

Eigenfunction answered 1/5, 2012 at 23:16 Comment(0)
M
0

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;

Mahout answered 22/8, 2017 at 17:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.