PDA

View Full Version : Perlberty


JRepici
09-06-2002, 10:52 PM
. . . . . . . . . . .
I remember feeling "holier-than-thow" toward the "all warnings off" programmers in my shop once. They'd turn "all warnings ON" just to, maybe dip a toe in those waters and get a scrolling screen for the next 15 seconds.

I, who always compiled all my C programs with ALL WARNINGS ON, and sometimes even brought my own lint from home, felt so smug, dare I say it, even superior. Perhaps this is penance then.

To learn Perl, I left all that stuff off the table. Didn't want it to clutter up the learning process early on the shallow part of the curve. Well, now I'm paying the price. If it hadn't been for the logs shutting off when there are too many errors, I'm quite sure I would have seen a 15 second scrolling screen.

First warnings
I got Pools or warnings, and that starts with 'P' and that... well you know the rest...


First. I can't seem to get "use warnings;" to work at all. It says it can't find the module "warnings.pm" in the path.
If I use warnings from the command line ('-w') I get warnings. Some are easy enough to solve, but others...

******* How do I suppress the "used only once" warning without doing too much confusing code around the configuration variables (they need to stay tidy for the user)

******* Uninitialized variables in C are those that are used before they've been on the left side of an assignment op. This does not seem to be the case in Perl. I get the warning, even if it is assigned directly above the statement that throws the warning. Sometimes it seems to just make no sense at all It seems to be mixed up with the %ENV hash somehow, but I can't make it out. And how about this, it gives me an un-unit'd variable on a 'print <<EOF;' statement ???


Now for 'strict'

The 'use strict;' pragma works just fine but it produces too many errors to list.


On the one I saw a lot of however, I' have a question:

When it says:

******* "$SomeVariableID" requires explicit package name at ..."

What does this mean. I thought everything was assumed to be in main if it doesn't have a package name? I've seen a lot of scripts with configuration variables and none of them ever included a package name before the variables. WTF?



A real-world question

I give my script to geek-b (me being geek-a of course) and he runs it on a MAC and it tells him that a function called in the code could not be found.

Yep, that function call is in the code, inside a function named OldDontUse(); that is itself never called.

The question: What is it about his system that allows him to catch (die over) this non-existent function-call at compile time even though it is never actually called at run time?

Put another way, how can I catch this at compile time?

also...

Are there more errors like this that will cause scripts to stop running on some systems while they run just fine on others?

. . . . . . . . . . .
Well, that's about it for now. As always I really appreciate all the expert help I get from you gurus on the FutureQuest staff and from all the guru-level site owners around here.

Thank you.

-John

Dunx
09-07-2002, 12:50 AM
OK, this is a big subject, but to start with a couple of the ones which I know the answers to...

1. the way to activate warnings from within the Perl script itself is in the #! line at the top (well, on Unix at least - on Windows I do not know), thus -

#!/usr/bin/perl -w

You can put other command line switches in there too. For instance, I often modify the include path (-I) to point to the place where my shared libraries are.

2. strict package warnings - what the strict module is complaining about is that your variables at package scope but are not qualified. As you say, unqualified package variables are assumed to be in package Main, but with strict active that isn't enough!

The easiest way to avoid these warnings is to declare everything lexically scoped, that is to use the "my" qualifier for all your variable declarations.

That should get you going, at least.

skolnick
09-07-2002, 09:30 AM
Originally posted by JRepici:

First. I can't seem to get "use warnings;" to work at all. It says it can't find the module "warnings.pm" in the path.

The "use warnings;" pragma showed up in Perl 5.6. If you are using an earlier version (say 5.005_3 in use here at FQ and quite common as it is still (I believe) the installation version for most Linux distributions) it is not supported. I use -w even though I develop on 5.6 (where it is still supported) so I won't have a conflict in production on 5.005 servers. BTW, I believe that Perl 5.8 is out.
How do I suppress the "used only once" warning without doing too much confusing code around the configuration variables (they need to stay tidy for the user)

Perl is trying to help you here. The underlying assumption is that you wouldn't put a variable in without using it more than once, so perhaps something is misspelled somewhere. Frankly the only time I have gotten this error when it wasn't really helping me was when I used a built-in Perl variable (it happened to be $0) in one and only place (a die statement). If you are running into this more often, why?

Uninitialized variables in C are those that are used before they've been on the left side of an assignment op. This does not seem to be the case in Perl. I get the warning, even if it is assigned directly above the statement that throws the warning. Sometimes it seems to just make no sense at all It seems to be mixed up with the %ENV hash somehow, but I can't make it out. And how about this, it gives me an un-unit'd variable on a 'print <<EOF;' statement ???

There are two issues here. With specific regard to initialization, you are probably getting caught by variable scope. Just because a variable is declared (with my or local) above a later invocation doesn't mean it is still in scope. Remember that braces (e.g. defining a loop) have their own scope. If you declare the variable before the loop and assign it in the loop, the value will persist beyond the loop, but if you declare and assign it within the loop (even if also declared outside the loop) the loop value will disappear outside of the loop. For a more coherent explanation see Perldoc (http://www.perldoc.com/perl5.005_03/pod/perlfaq7.html#What%27s-the-difference-between-dynamic-and-lexical-(static)-scoping---Between-local()-and-my()-) including the reference to Perlsub (http://www.perldoc.com/perl5.005_03/pod/perlsub.html#Private-Variables-via-my()), or just look in 'perldoc perlsub'. If you get through all that you will be so smart you won't be able to stand it. <grin>

The second, more irritating issue is that here documents confuse the parser's line numbering in the Perl compiler. This is a pain, but not enough of one to justify avoidance of the supremely useful here document. If you are like me, just swear under your breath and look somewhere else. You can also give the compiler a hint; a comment in the form of '#line xxx' on line xxx-1 will tell the compiler that the next line is xxx. I have NOT done this, but apparently the parser uses that numbering touch-stone for all subsequent lines, resetting the offset. See The Perl You Need to Know - Part 2 (http://perl.com/pub/a/2002/05/07/mod_perl.html) at O'Reilly. The article also talks about tracing warnings, some scope information (that presupposes some of the information in perldoc perlsub), and a snippet on perldoc.


The 'use strict;' pragma works just fine but it produces too many errors to list.


No, you just have *made* too many errors to list. <grin> In my experience a lot of these will go away if you set out to initialize all your variables in a consistent fashion. Remember when you suddenly "got it" about header files in C? All kinds of things started to get easier. Set up all your global variables (a bunch of my statements) near the front of your code, start each subroutine with declarations for the variables that you use throughout the subroutine, do all your declarations within loops and other internal blocks at the head of the block, and huge whacks of the errors will disappear. See 'perldoc perlstyle'.

In many cases, one error will result in a number of error messages. Did you ever use Fortran? In Fortran 77 on VMS, I might get 20 or 30 errors from one actual mistake. Fix the ones you understand and try again. 'perl -c program_name' is your friend. After a little practice and the development of some good habits 'use strict;' will become the safety net it is meant to be. If you don't start you won't get there.


"$SomeVariableID" requires explicit package name at ..."


Good news. We have already talked about this. With 'use strict;' in place, this is almost always a result of the scope of a variable declaration. Look for where you declared the variable and make sure the declaration is still in scope where you are using it.


I give my script to geek-b (me being geek-a of course) and he runs it on a MAC and it tells him that a function called in the code could not be found.

Yep, that function call is in the code, inside a function named OldDontUse(); that is itself never called.

The question: What is it about his system that allows him to catch (die over) this non-existent function-call at compile time even though it is never actually called at run time?

Put another way, how can I catch this at compile time?


I would guess he is using a different version of Perl than you are. Later versions of the Perl compiler are better and better at finding issues. My personal style, by the way is to comment out all the lines of code I don't want to lose but that aren't being used anymore.