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

An experienced pgmmr, I'm totally new to Perl, and appreciate any guidance you might provide.

I have 3 issues which I've been wrestling with for over a full day, and cannot find the answers:

At "Error1" below -- Whenever I run the scipt, I get the msg,

Can't call method "My" on an undefined value at G:\PERLCODE\NEWSCR~1.C +GI line 23."
But that's what I'm trying to do . . . define the value. And, without MAIN::, I get the error,
global symbol $LogMsg requires explicit package name".

At "Error2" -- I had understood that $^W = 0 would turn off the warnings, but it doesn't. Did I miss something?

Finally, at Error3 -- Without the "my $temp = $MAIN::Log;" statement, I get warnings about "$MAIN::Log only used once", but it's assigned a value at the beginning of MAIN, and then used in the write sub . . .

Thanks in advance for your help!!!

#! perl -w use strict; use diagnostics; use Time::localtime; use Config::IniFiles; MAIN:{ my $DirPath = 'A:\\TempIMS_Work\\Listings\\'; my $Logfile = 'DRS_FileModify.log'; my $StdErrfile = 'DRS_FileModify_StdErr.log'; my $Log = $DirPath.$Logfile; my $StdErr = $DirPath . $StdErrfile; # Just to get around warning of "Only Used Once" my $dummystmt = $Log . $StdErr; #Error1 My $MAIN::LogMsg = "\n\n" . &getDateTime() . "\ - Starting Processing\ +n\n"; # Start the log and StdErrLog &writeLog(); &writeStdErr(); # Ensure the log path exists opendir (Dir, $MAIN::DirPath) or die "\n\nCannot open the path for the processing log: $MAIN +::DirPath -- $!\n"; closedir(Dir); # Loop # Process each DRS file -- Call processDRS_File # EndLoop # If error, FTP the errmsg # if FTP failure, write to logs # if success, write o.k. msg to logs #EOJ } # Subroutines and Functions sub getDateTime {; my $tm = localtime(time); my $ampm = "am"; my $tempHour = undef; if ($tm->hour > 12) {$tempHour = $tm->hour - 12; $ampm = "pm"; } else { $tempHour = $tm->hour; }; return (sprintf("%02d/%02d/%02d %02d:%02d %02s", $tm->mon+1, $tm->mday, substr($tm->year + 1900, 2, 2), $tempHour, $tm->min, $ampm) ); }; sub writeLog() { #Error2 # $^W = 0; open LOGFILE, '>>', "$MAIN::Log" or die "ERROR: Cannot open Log file: $!"; # $^W = 1; #Error3 # my $temp = $MAIN::Log; print LOGFILE $MAIN::LogMsg; close LOGFILE; }; sub writeStdErr() { open STDERRFILE, '>>', "$MAIN::StdErr" or die "ERROR: Cannot open StdErr file: $!"; my $temp = $MAIN::StdErr; print STDERRFILE $MAIN::LogMsg; close STDERRFILE; };

Replies are listed 'Best First'.
Re: Newbie Q re: Undefined Value and "only used once" warnings
by ambrus (Abbot) on May 15, 2004 at 18:31 UTC

    Yes, perl is case sensitive, so my instead of My.

    About $^W= 0;, it runs at run-time, so it won't affect the "once" warning, which is generated at conpile-time. To remedy, either put the $^W in a begin-block (like BEGIN {$^W= 0;}), or with perl >=5.6, use the warnings pragma: no warnings "once"; turns off just the "once" warnings, and it's scoped lexically to the block, so you can write {no warnings; SOME CODE THAT WOULD GIVE A WARNING } and hush, the effect is gone when you close the block. (no warnings affects both compile-time and run-time warnings.)

    Corrected typo s/rub-time/run-time/ noted by arden. Thx.

Re: Newbie Q re: Undefined Value and "only used once" warnings
by ambrus (Abbot) on May 15, 2004 at 18:48 UTC

    About the third error. Unike some cases with the "only used once" warning, Perl is right here.

    You've messed up scoping rules, the $MAIN::Log you're trying to access is not the same as the $Log variable above.

    $MAIN::Log is the $Log variable of the MAIN package, which can not be your Log for two reasons. Firstly, you declare that $Log with my, so it's a lexical variable, which does not belong to any package, instead, it belongs to the innermost lexical scope in which the declaration is, which is in this case the brace-block labeled MAIN. If you declare a my variable in that block, you can use its name only in that block. Secondly, there's no MAIN package here. The loop label MAIN does not create a package, you have to use the package statement for that. (You might be thinking that you are in package MAIN by default, in the absencse of pkg declarations. Not, that's package main in lc.)

    There are two ways you could correct this. The first is that you use a lexical variable. You say my $Log before the opening of the MAIN loop, that way it is valid in the whole script (which is by itself a scope, although the largest one), and then you can refer it with $Log, that is, without a package name later.

    The second is that you really use a global variable. In this case, you first have to say package MAIN somewhere, or just write main instead, which is the default package. Then, you change the declaration to our $Log= ... at the assignment, and wow, it's a global variable you can access as $MAIN::log or $main::log depending in what package you've just set.

    The first solution is probably appropriate here, I've just written the second so that you know what $MAIN::Log really means here.

    (Someone knowing pm please recommend some good tutorial about my and our in this thread. Thx.)

Re: Newbie Q re: Undefined Value and "only used once" warnings
by Nkuvu (Priest) on May 15, 2004 at 19:11 UTC

    On a completely different note, I noticed that you're creating your own getDateTime function. It looks like you're duplicating effort.

    If you replace the use Time::localtime line with use POSIX qw(strftime), you can use the following line for formatting the time:

    strftime ("%D %l:%M %p", localtime)

    (note that that's a lowercase L for the hour) which prints out exactly what you have for getDateTime. Well, really close, I condensed two spaces between the date and the hour into one space. The format string I built from the formats given in man strftime -- but if you aren't running on a Un*x (or OS X) box you can Google for the manpages easily enough.

    There may very well be reasons you're not using strftime, I just wanted to make sure you're aware of the option.

Re: Newbie Q re: Undefined Value and "only used once" warnings
by exussum0 (Vicar) on May 15, 2004 at 17:42 UTC
Re: Newbie Q re: Undefined Value and "only used once" warnings
by arden (Curate) on May 15, 2004 at 18:33 UTC
    As sporty pointed out, Perl is very much so case sensitive! my is a built-in Perl function, whereas My doesn't have any special meaning, so Perl assumes that it's a custom method which you've neglected to include the code for.

    As for warnings, if you really want to get rid of all warnings, then add  no warnings; at the beginning of your code. Of course, if you have warnings turned off and are having problems, you're not likely to find a sympathetic crowd here at the Monastery. :)

    - - arden.

Re: Newbie Q re: Undefined Value and "only used once" warnings
by Errto (Vicar) on May 15, 2004 at 19:31 UTC

    Another issue that the above posts touch on is your use of package variables. When you refer to $MAIN::Log, that is being treated as the variable called $Log in the package MAIN. This has nothing to do with your declaration MAIN:, which is merely creating a line label that you could use in a next or last statement. If you really want a package, you should declare it with package MAIN;. But I think a better idea, would be to put your decalarations like this:

    my $Log; my $LogMsg; my $StdErr;

    at the very top of your program outside any blocks. Then remove all the MAIN:: references everywhere you have them now.

      Thank you all!!!!!!!!!!

      These are all very valid points, well explained, and VERY much appreciated, as I learn Perl while developing an application under time constraints at work!