Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Uninitialized value ?

by All0uette (Acolyte)
on Aug 20, 2001 at 17:13 UTC ( [id://106210]=perlquestion: print w/replies, xml ) Need Help??

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

As a two day learner of perl I've come across the following, basically I'm messing around with the examples in the O'reilly Learning Perl. Use of uninitialized value at perky-array line 38, <> chunk 1. The script still works but I get the following error when the 'loop' related to an unkown user kicks in ? Can anyone help an (obvious) initiate:
#!/usr/bin/perl -w ###@words = ("camel", "llama", "alpaca"); ### ### #or ### #@words = qw(camel llama alpaca); # qw acts to specify "" to each + variable ### ### Above shows the use of an 'array' - the following describes an 'ha +sh' ### shown as %a (see 'pinky' for full program) %words = qw ( fred camel barney llama betty alpaca wilma alpaca ); print "What is your name? "; $name = <>; chomp $name; if ($name eq "pete") { print "Hello, $name! \n"; } else { print "Hello $name,\n "; $secretword = $words{$name}; # gets secret word #### problem seems to start here ##### if ($secretword eq "") {$secretword = "groucho"; } print "What's the secret word ?\n"; $guess = <>; chomp ($guess); while ($guess ne $secretword) { print " Niet - try again, What is the secret word ?\n"; $guess = <>; chomp ($guess); } }

Edit Masem 2001-08-22 - Code reformatting to make easier to read

Replies are listed 'Best First'.
Re: Uninitialized value ?
by busunsl (Vicar) on Aug 20, 2001 at 17:22 UTC
    When you try to get a value for a key which is not in the hash, you'll get an undefined value.
    That undefined value is not equal to "".
    You can check undefined values with defined.

    Try:

    $secretword = $words{$name}; # gets secret word if (! defined $secretword) { }
      You fill your hash:
      %words = qw ( fred camel barney llama betty alpaca wilma alpaca );
      It now contains four elements with the names of famous actors as keys.

      If the user enters one of the keys, everything will be fine, because e.g. $words{fred} is defined, so $secretword will get the value 'camel'.
      If the user enters something, that is not in the list of keys, e.g. 'busunsl', then $words{busunsl} is not defined.
      And $secretword will become undef.

      And you check for an undef value with defined.

      You wanted to fill something into $secretword if there was nothing in it, that is, if it is undef.
      So your if-statement has to be: if (! defined $secretword) { With the ! meaning 'not'.

        This however alters the way the program works.
        if (!defined $secretword or $secretword eq '') {
        It will now both check if $secretword has some value (possible empty) and if it is empty.
        This can be boiled down to the line
        if (!$secretword) {
        or if you like the unless operator:
        unless ($secretword) {


        T I M T O W T D I
      busunsl, Thanks for that - it seems to work - although I'm still not sure why the original didn't. Especially as I got this form the book ! Any chance you can explain a lttle more. Cheers.

        I think your code should work correctly - in both versions. The only difference is that you get once a warning (which is exactly that, it's not an error) and iirc these early examples in merlyn's book (I suspect you are reading the llama) don't run under -w and strict because he hasn't introduced all the concepts yet.

        In if ($words{$name} eq "") the key $name is looked up in the hash %words. This returns undef when the key $name does not exist in %words. The undef is then compared to "" with a string compare, so the undef is transformed into the empty string. This results in the comparision being true. But this might be a source of error, so perl warns you if you have warnings enabled (-w).

        Why might that be a source of error? Well, imagine the empty string would be a valid entry in your hash, then you get the same result no matter if the key does not exist or the value is empty. Some code:

        #/usr/bin/perl -w use strict; my %hash; $hash{key1} = ""; # this produces no warning if ($hash{key1} eq "") { # true print "key1 empty!\n"; } # this produces a warning if ($hash{key2} eq "") { # true print "key2 empty!\n"; }
        to circumvent this look at defined (like suggested by busunsl) and for hashes also interesting exists.

        -- Hofmator

Re: Uninitialized value ?
by mexnix (Pilgrim) on Aug 20, 2001 at 18:00 UTC
    Try doing this:
    #...your code... print "Hello $name,\n "; $secretword = $words{$name} || 'groucho'; #....more code written by you...
    what this does is, if the name $name is not in your list, mexnix currently isn't, it automatically assigns "groucho" to $secretword. || is logical OR and you can find it in your perldoc perlop manpage. With this, you can even skip the if ($secretword eq "") { $secretword = "groucho"} stuff, because it already does it for you. My $0.02

    __________________________________________________

    s mmgfbs nf, nfyojy m,tr yb-zya-zy,s zfzphz,print;
    - thanks japhy :)

    mexnix.perlmonk.org

      and what this also does is bite you back horribly ;-)
      if your $words{$name} evaluates to false, i.e. '' or 0. So better - unless you can outrule those cases: $secretword = defined($words{$name}) ? $words{$name} : 'groucho';

      -- Hofmator

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://106210]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2024-04-26 03:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found