NamfFohyr has asked for the wisdom of the Perl Monks concerning the following question:

I've been debugging a simple script to rename and copy a directory of files. It's shown below (minus the comments). The first command line argument is a name stem (all target files match the $stem), the second is a range/iterator, the third is a target directory and filename. The first three prints are for debugging.
my $stem = $ARGV[0]; my $start = $ARGV[1]; my $dir = $ARGV[2]; print "STEM: $stem\n"; print "START: $start\n"; print "DIR: $dir\n"; my $outstring; while(<*.pdb*>){ if(m,\.viols,){next} if(m,$stem,){ chomp; $outstring = $dir.$start.'.pdb'; print `cp $_ $outstring\n`; $start++}}
When I run with "use Strict" (as is my default these days, along with warnings) I get "unitialized variable messages" typically indicating I did something less-than-ideal. The print flags above show that $stem, set to $ARGV[0] is not getting defined (but the other arguments are). There is some cryptic and suspect output from Strict regarding "Subroutine bits redefined":
Subroutine bits redefined at /System/Library/Perl/5.8.6/strict.pm line + 11. Subroutine import redefined at /System/Library/Perl/5.8.6/strict.pm li +ne 27. Subroutine unimport redefined at /System/Library/Perl/5.8.6/strict.pm +line 32. Use of uninitialized value in concatenation (.) or string at rename4li +b.pl line 16.
When I stop using Strict, the error messages go away and the debug prints now give the expected output. Everything's hunky dory. The ouput's as expected. Is this something regarding Strict that I don't understand (for example, does it sanity check/filter command line arguments)?

I don't want my subroutine bits defined, do I? I'm alone and frightened.

Thanks much,
ry

"I'm not afraid of Al Quaeda. I'm afraid of Al Cracker." -Chris Rock

Replies are listed 'Best First'.
Re: use Strict: a rigorous way to break my command line variables?
by tilly (Archbishop) on Aug 09, 2006 at 02:24 UTC
    Change use Strict; to use strict;

    Short explanation: The name of the module is strict, all lower case. Because Windows is case insensitive, use Strict; will load the module even though it is already loaded. It won't do anything useful with it, but it will load it. Since it was already loaded by something else (or else something else loads it after you did), you get redefinition warnings and no useful effect. Change it to the proper case and you'll have no redefinition warnings, and the module will do something for you.

    Long explanation. When you type use Strict; Perl proceeds to do the following:

    BEGIN { require Strict; Strict->import(); }
    require checks %INC to see whether "Strict.pm" is loaded, and then tries to load it if not. However %INC is case sensitive, so it won't notice that Strict.pm is there if it is looking for strict.pm, and vice versa. Since Windows is case insensitive, if you look for Strict.pm you'll find strict.pm. So Perl decides it doesn't have the module, and tries to load it. Since you're loading the same code twice, you get redefinition errors.

    Your bigger problem, though, is that the line Strict->import(); won't do anything useful. You see strict.pm only implements strict::import. So there is no Strict::import to find, and nothing happens.

    So make it use strict; and Perl will not try to reload the same module, and (more importantly) Perl will make the method call that turns strict on in your code.

      Oh wow. Thanks, tilly, you got it. I'm using MaxOSX though, hurumph;)

      I did type "use Strict" instead of "use strict." When I change it to the lowercase version, everything works again.

      Don't know why I used uppercase. Perhaps it seemed Even Stricter!

      ry

      "I'm not afraid of Al Quaeda. I'm afraid of Al Cracker." -Chris Rock
        When I see people using a case insensitive filesystem, I just assume they are using Windows.

        Bad assumption. Sorry.

        it's funny, on the p5p mailing list today, somebody had filed a bug concerning this *exact* problem; Rafael actually answered by quoting the perl source that was saying that this could not be fixed, that the *previous* fix was bad and had been withdrawn, and the rationale behind it. The truth is that this kind of filesystem **should** be fixed!

      Curiously, this code runs fine when I try it on a Mac (OSX) under perl 5.8.6, when either "use strict;" or "use Strict" is added at the top (with or without "use warnings;" before it).
        I assumed that the OP had not included all of the code necessary to generate the error. Add more code that loads something that loads the other one. Then you'll get the warning.

        Also try use Strict; then try doing something that strict is not supposed to allow. It will be allowed. It should not be.

Re: use Strict: a rigorous way to break my command line variables?
by GrandFather (Saint) on Aug 09, 2006 at 02:20 UTC

    I don't see your use of use strict; use warnings; in your sample. Perhaps you could pare down your code to a minimum that demonstrates the problem and tell us what version of Perl you are using.

    If I add strictures to the code as you have given it, then run it with nothing on the command line, it generates three "Use of uninitialized value" warnings as expected.


    DWIM is Perl's answer to Gödel