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

All the PERL books that I own, dont touch on use warnings except to say that you should use it.
But the problem is, it doesn't tell me all I need to know HOW to use it.

Here is the problem. I have writen a script to find the last logon date for users on the domain. It works fine, but when I turn warnings on, It warns me about the second line in this section of code.
Win32API::Net::UserGetInfo('\\\\'.$SERVER, $USER, 3, \%USER_INFO); if ( %USERLIST->{$USER}->{'TIME'} < %USER_INFO->{'LastLogon'}) { %USERLIST->{$USER}->{'TIME'} = %USER_INFO->{'lastLogon'}; %USERLIST->{$USER}->{'DISABLED'} = "DISABLED" if (%USER_INFO->{' +flags'} & UF_ACCOUNTDISABLE) } }
it saysUse of uninitialized value in numeric lt (<) at D:\BIN\SCRIPTS\PerlScripts\45daysold\45daysold.pl line 44 I already have a "my %USERLIST;" in the code, so how do I declare the anonymous hashes?

BatGnat

Replies are listed 'Best First'.
(Ovid) Re: Warnings, and declaring Hashes of Hashes.
by Ovid (Cardinal) on Nov 30, 2000 at 02:43 UTC
    You need to ensure that you are testing scalars. %USERLIST->{$USER}->{'TIME'} should be written as $USERLIST->{$USER}->{'TIME'} (note the leading dollar sign). In this case, you're evaluating the entire hash in scalar context. That's going to have unpredictable results.

    Cheers,
    Ovid

    Update: I tested your method of looking up hash elements and it appears to work:

    use warnings; my %hash1 = ( test => 3 ); my %hash2 = ( bobby => 15, what => 'thehell' ); print "good\n" if %hash1->{'test'} < %hash2->{'bobby'}; print "good1\n" if $hash1{'test'} < $hash2{'bobby'};
    However, it is definitely not how it's usually done and I suspect you'll find that most agree that using the $ first is preferable. Not sure if there are any issues with the other way.

    Also, just because you have a particular key in existence does not mean that it's defined.

    Make sure that %USERLIST->{...} is changed to $USERLIST{...}.

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      For reasons that I've never been able to get an answer to, the following syntax is valid:
      @array->[$idx]; %hash->{$key};


      japhy -- Perl and Regex Hacker
        Here's a guess :)

        The -> notation implies a context -- in fact, it implies that whatever to the left is a reference, and whatever is to its right is "owned" by the referred-to object.

        Perl seems pretty smart about context.

        So, in these cases, it interprets the thing to the left as a reference to the object named, and voila, does the right thing, since the "members" are being referred to properly.

        If you try to use ref() on the whole "thing" (hash or array) you won't see it as a reference because it is simply interpreting the "thing" in a scalar context, though.

        Update:
        Looking in perlref there is the cryptic comment:

        . References of the appropriate type can spring into existence if you dereference them in a context that assumes they exist. Because we haven't talked about dereferencing yet, we can't show you any examples yet.

        (See number 6).

        I'm guessing that's the case here.

      now i get this
      Name "main::USERLIST" used only once: possible typo at D:\BIN\SCRIPTS\ +PerlScripts\45daysold\45daysold.pl line 44. Name "main::USER_INFO" used only once: possible typo at D:\BIN\SCRIPTS +\PerlScripts\45daysold\45daysold.pl line 44.
      after chnaging it to this if ( $USERLIST->{$USER}->{'TIME'} < $USER_INFO->{'LastLogon'})
Re: Warnings, and declaring Hashes of Hashes.
by chipmunk (Parson) on Nov 30, 2000 at 02:50 UTC
    I think you may be getting this warning because your hash keys are not consistent. if ( %USERLIST->{$USER}->{'TIME'} < %USER_INFO->{'LastLogon'}) vs. %USERLIST->{$USER}->{'TIME'} = %USER_INFO->{'lastLogon'}; One line uses LastLogon, both L's capitalized, while the other lastLogon, only the second L capitalized. The documentation for the Windows module you are using should state which is the correct spelling.

    I notice that you are using an odd syntax for looking up hash keys. While %hash->{key} seems to work, the proper syntax is $hash{key}. The $ indicates that this is a scalar value, while the {key} indicates that it is an element of a hash.

    Finally, regarding the question about warnings. my %USERLIST is unrelated to the issue of uninitialized value warnings, which apply only to scalar values. You may want something like this:

    if (defined $USERLIST{$USER}{'TIME'} and defined $USER_INFO{'LastLogon'} and $USERLIST{$USER}{'TIME'} < $USER_INFO{'LastLogon'})
      Thanks to all I solved the problem using this
      if (not defined $USERLIST{$USER}{'TIME'}) {$USERLIST{$USER}{'TIME'}=0} if ( $USERLIST{$USER}{'TIME'} < $USER_INFO{'lastLogon'}) { %USERLIST->{$USER}->{'TIME'} = $USER_INFO{'lastLogon'}; %USERLIST->{$USER}->{'DISABLED'} = "DISABLED" if ($USER_INFO{'flags +'} & UF_ACCOUNTDISABLE) }
Re: Warnings, and declaring Hashes of Hashes.
by runrig (Abbot) on Nov 30, 2000 at 02:53 UTC
    Whenever you declare the anonymous hashes, initialize the appropriate elements (TIME & LastLogon it looks like) to zero. Also it looks like you have a typo - in one instance you have 'LastLogon' and in another you have 'lastLogon'.

    P.S. I for one was suprised that this even worked at all, let alone without errors or warnings. Can anyone point me to some documentation or explain this syntax:
    #!/usr/local/bin/perl -l -w use strict; my %hsh; # Not '$hsh{hello} = 1' ???!!! %hsh->{hello} = 1; for (keys %hsh) { print "$_=$hsh{$_}"; }