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

Hello fellow Monks, I have a few questions. I am very new to Perl scripting, and I need some help with use strict; Whenever I declare use strict; at the beginning of the script, perl spits out an error where a bunch of variables are wrong. I double, triple, and quadruple checked that all of my variables are declared with 'my', but it keeps giving me that error. I am also facing an organization dilemma. As you can see, this script is very badly set up, but is there any other way to process this data?
print "#---------mRFLoYDFrEAK42's---------#\n"; print "| DOOM Log Parser |\n"; print "#----------------------------------#\n\n"; if (defined $savegame) { print "Game saved $savegame times.\n\n"; } if (defined $deathcnt) { print "Died $deathcnt times.\n\n"; } if (defined $clipsobt) { print "You have obtained $clipsobt clips.\n"; + } if (defined $ammbxobt) { print "You have obtained $ammbxobt boxes of a +mmo.\n"; } if (defined $shelsobt) { print "You have obtained $shelsobt shells.\n" +; } if (defined $shlbxobt) { print "You have obtained $shlbxobt boxes of s +hells.\n"; } print "-------------------------------------\n"; if (defined $shotgobt) { print "You have obtained $shotgobt shotguns.\ +n"; } print "-------------------------------------\n"; if (defined $armorobt) { print "You have obtained $armorobt Armors.\n" +; } if (defined $megarobt) { print "You have obtained $megarobt MegaArmors +.\n"; } if (defined $armboobt) { print "You have obtained $armboobt armor bonu +ses.\n"; } if (defined $helboobt) { print "You have obtained $helboobt health bon +uses.\n"; } if (defined $medikobt) { print "You have obtained $medikobt medikits.\ +n"; } if (defined $stipkobt) { print "You have obtained $stipkobt stimpacks. +\n"; } print "-------------------------------------\n"; if (defined $redkcobt) { print "You have obtained $redkcobt red keycar +ds.\n"; } if (defined $blukcobt) { print "You have obtained $blukcobt blue keyca +rds.\n"; } if (defined $yelkcobt) { print "You have obtained $yelkcobt yellow key +cards.\n"; } print "-------------------------------------\n"; if (defined $backpobt) { print "You have obtained $backpobt backpacks. +\n"; } if (defined $besrkobt) { print "You have obtained $besrkobt berserk pa +cks.\n"; } print "-------------------------------------\n"; if (defined $secrtobt) { print "You have discovered $secrtobt secrets. +\n"; }

Replies are listed 'Best First'.
Re: help with "use strict" and code organization
by swampyankee (Parson) on Apr 24, 2008 at 01:04 UTC

    Strict and its siblings, warnings and diagnostics don't introduce errors; they reveal them. Strict requires you to declare each variable using the "my" function, within the appropriate scoping unit (to a first, and doubtless overly simplified, approximation, the innermost braces which contains the variable and its declaration).


    Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: help with "use strict" and code organization
by thezip (Vicar) on Apr 24, 2008 at 06:16 UTC

    MrFloydFreak42 ,

    • Before you can refer to any of the variables (ie. $savegame, $deathcnt, etc.), you will need to declare each of them using "my".

    • Since your usage for each of these variables is as an integer, you'd do well to explicitly initialize them to zero:
      use strict; use warnings; my $savegame = 0; my $deathcnt = 0; ... then initialize the rest of your vars ... ... read the log file and accumulate the counts for each variable ...
    • Once you have accumulated the various counts, you can do something like:
      my $msgformat = "You have obtained %d %s.\n"; if ($shotgobt) { printf $msgformat, $shotgobt, "shotguns") }; if ($armorobt) { printf $msgformat, $armorobt, "Armors") }; ... do the same type of thing for the rest of the messages ...
    • One radical change you could do is to completely eliminate the scalar variables all together, and just use a hash to accumulate the values, such as:
      my %stats = ( 'clips' => 6, 'boxes of ammo' => 2, 'shells' => 47, 'boxes of shells' => 3, 'shotguns' => 2, 'Armors' => 2, 'health bonuses' => 1, 'medikits' => 4, 'stimpacks' => 2, 'yellow keycards' => 1, 'backpacks' => 1, 'berserk packs' => 1, );
      As you parse your log file, you'll just accumulate the values into the appropriate hash keys. Then it's just a matter of printing out the keys and their values, like:
      my $msgformat = "You have obtained %d %s.\n"; for my $stat (keys %stats) { printf $msgformat, $stats{$stat}, $stat; }
    • You'll notice that some keys don't exist in the hash table. That's because values never accumulated for them during your parsing

    • If you need to show the keys in a particular order, you could create an array of the keynames and use that array instead of keys %stats

    • Then there are also the cases where the message labels don't match the "You have obtained" format. These are also not stored in the hash, but can be stored in their own scalars and handled separately.

    Your wish is my commandline.
Re: help with "use strict" and code organization
by Cody Pendant (Prior) on Apr 24, 2008 at 02:35 UTC
    One possible reason for this problem is that you've defined them using my, but you've defined them in the wrong place.

    For instance, if you've done

    if($foo){ my $bar = 'baz'; } print $bar;
    Then you'll get the warning that $bar is undefined, because it only exists inside the "if" block.

    In other words, just adding my anywhere you declare a variable isn't going to solve your strict problems. You have to know what it means for those variables.



    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...
Re: help with "use strict" and code organization
by toolic (Bishop) on Apr 24, 2008 at 01:04 UTC
    This snippet compiles without errors:
    #!/usr/bin/env perl use warnings; use strict; my $savegame; print "#---------mRFLoYDFrEAK42's---------#\n"; print "| DOOM Log Parser |\n"; print "#----------------------------------#\n\n"; if (defined $savegame) { print "Game saved $savegame times.\n\n"; }

    and prints:

    #---------mRFLoYDFrEAK42's---------# | DOOM Log Parser | #----------------------------------#

    Perhaps you could reduce your code to just a few lines, including the my declarations, and show us your exact error messages. When debugging, I always find it useful to reduce my code to the fewest lines possible to still get the error messages.

      The error messages output by perl are along the lines of: Global symbol "$whatever" requires explicit package name at ......... They all have a big file location at the end. This has to do something with strictures but all my variables are defined with my.
Re: help with "use strict" and code organization
by ysth (Canon) on Apr 24, 2008 at 02:07 UTC
    my (lexical) variables are lexically scoped; they are only usable from where they were declared to the end of the innermost enclosing block. Usually this means up to the next } that ends a block.

    Since you have declared the variables in question with my() (though you haven't shown that part) and it is still treating some of your attempts to use the variables as undeclared global, the scope your declaration probably doesn't extend to where you are using them.

Re: help with "use strict" and code organization
by runrig (Abbot) on Apr 24, 2008 at 01:10 UTC
    Whenever I declare use strict; at the beginning of the script, perl spits out an error where a bunch of variables are wrong.

    Look at the errors one at a time (start with the first one). There should be line numbers with the errors. Fix each error one at a time. You can get just those errors by running "perl -c your_program_name".

    Perhaps Use strict and warnings (or one of the nodes it links to) will help.

Re: help with "use strict" and code organization
by tachyon-II (Chaplain) on Apr 24, 2008 at 01:12 UTC

    Yes this is badly organised but you do not show any data processing. You have a series of lines of the format

    if ( $this ) { print "You have obtained $this this stuff\n"; }

    How you got to this stage is not show, nor is a sample of the file format you are parsing. strict works fine and the errors you get will have a meaning. You need to post some sample log data your complete code if you really want answers. Use <readmore> tag to hide lengthy stuff like the data and code. Ask specific questions like "Why does strict complain about this?", "How can I parse this data efficiently?" or like you have said "This is ugly but I don't know enough perl to make it better. Suggestions welcome!"

Re: help with "use strict" and code organization
by apl (Monsignor) on Apr 24, 2008 at 01:09 UTC
    Whenever I declare use strict; at the beginning of the script, perl spits out an error where a bunch of variables are wrong. I double, triple, and quadruple checked that all of my variables are declared with 'my', but it keeps giving me that error.

    Meet us halfway: what did your my statements look like, and what was the error that was produced?