In this meditation,
An Interesting Gotcha With use/require, I pondered a little warning involving the loading of the same module twice due to the case insensitivity of the Windows platform. I believe I understand why the warning occurred but I am not sure I understand how. Please consider my reasoning ...
Each package is compiled in its own namespace regardless of how it was brought into the picture which means in this context that functions are compiled and typeglobs to those functions are loaded into the package symbol table etc.. Functions are imported into (or exported from) a package by aliasing the function typeglobs in one package into the symbol tables of another (camel book 2nd ed pg 294).
Consider this case, a main program goes along and calls "
use File::Basename;". The package namespace File::Basename is created, functions are compiled and, since File::Basename exports its function by default, the appropriate aliases to those functions are loaded into the symbol table for main::. A little while later, a library module is loaded that also "uses" File::Basename referencing the module with a different to perl but not to the OS syntax (File::Basename vs File::BaseName). Since the OS understands this to be the same file, File::Basename is again loaded. However, the namespace File::Basename already exists, so perl just recompiles the functions which resultes in the "subroutine redefined in File::Basename ... " warning (see readmore). This leads me to believe that what is happening is happening inside the File::Basename namespace. This belief is supported by the fact that the warning references only File::Basename and not the main or library packages in any way.
So far this makes sense, my question is, then, if the warning is not relevent to the main:: or library namespaces, why did the warning stop when I suppressed all automatic subroutine exporting to those packages? If I load File::Basename with the statement "
use File::Basename();" in either main or the library (or both), I do not get the warning all else being the same. This suggests that the redifinition is occuring through or relative to the main:: or library namespaces which seems to contradict my previous reasoning.
What am I missing about package loading and namespaces that would reconcile these two behaviours?
Update:
Thanks for the great comments. I'm still not sure I have my answer though. Theoretically, the use statements in the main and library modules are in seperate namespaces. the main program does not import anything from the library module which implies that when File::Basename is "used", it is exporting its functions into distinct namespaces so there shouldn't be a clash. But there is which implies that File::Basename is exporting its functions into the same namespace. But which one? and why? I've looked at Basename.pm and I can't see where this might be happening. Something in the Exporter module maybe? And, if the clash is in the File::Basename namespace why does turning off automatic exportation stop the warning? Any ideas where I might go to research this further?
# stripped down test code
#!/usr/local/ActivePerl-5.6/bin/perl
use strict;
use warnings;
use diagnostics;
use File::BaseName;
printf("%-45s%-s\n",$_,$INC{$_}) foreach (sort keys %INC);
package prob_func;
sub secondfunc{
use File::Basename;
return;
}
__OUTPUT__
#(relevent parts only)
Subroutine fileparse_set_fstype redefined at C:/Program
Files/Perl/lib/File/Basename.pm line 152 (#1)
(W redefine) You redefined a subroutine. To suppress this warning
+, say
{
no warnings;
eval "sub name { ... }";
}
Subroutine fileparse redefined at C:/Program Files/Perl/lib/File/Basen
+ame.pm
line 166 (#1)
Subroutine basename redefined at C:/Program Files/Perl/lib/File/Basena
+me.pm
line 222 (#1)
Subroutine dirname redefined at C:/Program Files/Perl/lib/File/Basenam
+e.pm line
235 (#1)
File/BaseName.pm C:/Program Files/Perl/lib
+/File/BaseName.pm
File/Basename.pm C:/Program Files/Perl/lib
+/File/Basename.pm
PJ
use strict; use warnings; use diagnostics;