Use of uninitialized value: when don't you get that?

Discussion in 'Perl Misc' started by Tim McDaniel, Dec 15, 2011.

  1. Tim McDaniel

    Tim McDaniel Guest

    I like to have "use strict" and "use warnings" (actually, "-w" on my
    scripts). I'm now wondering: when can you use an undefined value and
    not get the "Use of uninitialized value" warning. Experimentally, I
    don't get the warning with

    my $x = undef;
    my $y = undef;
    if ($y) { ... }
    if (! $y) { ... }
    if ($y && ! $y) { ... }
    if (exists $x->{notdef}) { ... }
    if (defined $x->{notdef}) { ... }
    if ($x->{notdef}) { ... }
    # and none of those autovivify it.

    (at least under Perl 5.008008, which is what my workplace uses).

    Is there a more complete listing of conditions that cause the warning
    and/or those that do not? I consider "using the value" to be an
    insufficient explantion, because I consider "if ($y)" to be a use of
    the value. "Using the value with an operator" covers cases like "+"
    and "." and "eq", but it doesn't work for me because "&&" is an
    operator too.

    --
    Tim McDaniel,
    Tim McDaniel, Dec 15, 2011
    #1
    1. Advertising

  2. Tim McDaniel

    Lucien Coffe Guest

    Tim McDaniel wrote :

    > I like to have "use strict" and "use warnings" (actually, "-w" on my
    > scripts).


    I think the "use warnings" way is the recommended way. It is scoped to
    the file/package, and is clearer.

    > I'm now wondering: when can you use an undefined value and
    > not get the "Use of uninitialized value" warning. Experimentally, I
    > don't get the warning with
    >
    > my $x = undef;
    > my $y = undef;
    > if ($y) { ... }
    > if (! $y) { ... }
    > if ($y && ! $y) { ... }
    > if (exists $x->{notdef}) { ... }
    > if (defined $x->{notdef}) { ... }
    > if ($x->{notdef}) { ... }
    > # and none of those autovivify it.
    >
    > (at least under Perl 5.008008, which is what my workplace uses).
    >
    > Is there a more complete listing of conditions that cause the warning
    > and/or those that do not? I consider "using the value" to be an
    > insufficient explantion, because I consider "if ($y)" to be a use of the
    > value. "Using the value with an operator" covers cases like "+" and "."
    > and "eq", but it doesn't work for me because "&&" is an operator too.


    Put it that way : *undef* can be true or false; In list context it is
    true, in all scalar contexts it is false. So testing it is not a problem.

    #!/usr/bin/perl
    use strict;
    use warnings;
    use diagnostics;

    my $x = undef;
    print 1,"\n" if( [ $x ] ); # true
    print 2,"\n" if( $x ); # false
    print 3,"\n" if( $x++ ); # false

    $x = undef;
    print 4,"\n" if( ++$x ); # true

    $x = undef;
    print 5,"\n" if ref $x; # false
    print 6,"\n" if( $x->{foo} ); # true
    print 7,"\n" if ref $x; # now true, ref $x = HASH

    $x = undef;
    print 8,"\n" if( "$x" ); # w uninitialized
    print 9,"\n" if( $x == 1 ); # w uninitialized


    Output from the diagnostics pragma :

    (W uninitialized) An undefined value was used as if it were already
    defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

    So if you use undef explicitly as a string or as a numeric value, you get
    the warning. Hope this helps.
    Lucien Coffe, Dec 16, 2011
    #2
    1. Advertising

  3. Tim McDaniel

    Lucien Coffe Guest

    Lucien Coffe wrote :

    > So if you use undef explicitly as a string or as a numeric value, you
    > get the warning.


    * If you use it explicitly as a string, or if you compare it as a
    numerical value.

    > Hope this helps.
    Lucien Coffe, Dec 16, 2011
    #3
  4. Tim McDaniel

    Lucien Coffe Guest

    Lucien Coffe wrote :

    > Lucien Coffe wrote :
    >
    >> So if you use undef explicitly as a string or as a numeric value, you
    >> get the warning.

    >
    > * If you use it explicitly as a string, or if you compare it as a
    > numerical value.
    >
    >> Hope this helps.


    Bumping again.

    $x = undef;
    print 10,"\n" if( $x+1 ); # w uninitialized

    undef++ is undef, ++undef is 1, undef+1 triggers the warning because you
    try to interpret undef to it's numerical value to use the + operator.
    Someone correct me if I'm wrong.
    Lucien Coffe, Dec 16, 2011
    #4
  5. Tim McDaniel

    Tim McDaniel Guest

    In article <jcf0j0$7e7$>,
    Lucien Coffe <> wrote:
    >Tim McDaniel wrote :
    >
    >> I like to have "use strict" and "use warnings" (actually, "-w" on
    >> my scripts).

    >
    >I think the "use warnings" way is the recommended way. It is scoped
    >to the file/package, and is clearer.


    Quite so, quite so. I was thinking of the scripts that I've done for
    myself, where there's just one file and I'm invoking it as a command.
    (I started with Perl 4.036, I think: I'm pretty sure "use warnings"
    didn't exist; I don't remember whether "my" even existed, and I
    suspect not.)

    --
    Tim McDaniel,
    Tim McDaniel, Dec 16, 2011
    #5
  6. Tim McDaniel

    Tim McDaniel Guest

    In article <jcf0j0$7e7$>,
    Lucien Coffe <> wrote:
    >Put it that way : *undef* can be true or false; In list context it is
    >true, in all scalar contexts it is false.


    As I understand it, a boolean context is not a list context, and if
    you use undef in a list context, it's put into a list of one element,
    which evaluates as true regardless of what that element is.

    My understanding is that there is really no undef in a list context:
    if you use it in a list context, it is put into a list of one element,
    and a list of one element evaluates as true in a boolean context
    regardless of what that element is.

    >my $x = undef;
    >print 1,"\n" if( [ $x ] ); # true


    That's testing [...], not undef or lists.

    print 1.1,"\n" if( [ ] );

    prints 1.1. [...] generates a reference to a list, and a reference to
    a list evaluates as true regardless of what the elements are or even,
    apparently, whether there are even any elements.

    >print 6,"\n" if( $x->{foo} ); # true


    False in 5.014002 on NetBSD, 5.008008 on something, and I would be
    astonished if it were true anywhere.

    >print 7,"\n" if ref $x; # now true, ref $x = HASH


    That's true.


    Looking further at "man perldiag":

    Use of uninitialized value%s

    (W uninitialized) An undefined value was used as if it were
    already defined. It was interpreted as a "" or a 0, but maybe it
    was a mistake. ...

    I'm thinking that the first sentence is somewhat imprecise or unclear.
    I think the second sentence is the condition: "Use of uninitialized
    value" occurs if and only if you use an undef value with an operator
    that requires numeric operands (like +, *, ==) or string operands
    (like ., printf "%s", split), and not otherwise.

    But I'd like to hear from someone authoritative, like someone who
    knows how to navigate the source for "perl".

    --
    Tim McDaniel,
    Tim McDaniel, Dec 16, 2011
    #6
  7. Lucien Coffe <> writes:

    [...]


    > Put it that way : *undef* can be true or false; In list context it is
    > true, in all scalar contexts it is false.


    This is wrong. Invoking a subroutine returning undef in list context
    effectivelty causes that to return a list containing a single element
    whose value is 'the undefined value'. If this list is assigned to an
    array and the array then evaluated in scalar context, the result will
    be the number 1 which is regarded as true:

    [rw@sapphire]~ $perl -de 0

    Loading DB routines from perl5db.pl version 1.32
    Editor support available.

    Enter h or `h h' for help, or `man perldebug' for more help.

    main::(-e:1): 0
    DB<1> sub axtmoerder { return undef; }

    DB<2> @a = axtmoerder

    DB<3> p scalar(@a)
    1
    DB<4> p $a[0] || 3
    3

    [...]

    > Output from the diagnostics pragma :
    >
    > (W uninitialized) An undefined value was used as if it were already
    > defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
    > To suppress this warning assign a defined value to your variables.


    I really think 'we' need another warning whose diagnostics output
    should roughly be like this:

    An addition operator was used. This was interpreted as an
    addition but maybe it was a mistake. To suppress this warning,
    add the comment # I mean it !!1 to the corresponding line of
    the code.
    Rainer Weikusat, Dec 16, 2011
    #7
  8. Tim McDaniel

    Tim McDaniel Guest

    In article <jcdo8q$doi$>,
    Tim McDaniel <> wrote:
    >Is there a more complete listing of conditions that cause the warning
    >and/or those that do not?


    I hit on the right search terms (if only I knew what they were).
    http://www.perlmonks.org/?node_id=862 by ambrus, from 2005, points to
    perlsyn. The current version says

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Declarations

    The only things you need to declare in Perl are report formats and
    subroutines (and sometimes not even subroutines). A variable holds
    the undefined value ("undef") until it has been assigned a defined
    value, which is anything other than "undef". When used as a number,
    "undef" is treated as 0; when used as a string, it is treated as the
    empty string, ""; and when used as a reference that isn't being
    assigned to, it is treated as an error. If you enable warnings,
    you'll be notified of an uninitialized value whenever you treat
    "undef" as a string or a number. Well, usually. Boolean contexts,
    such as:

    my $a;
    if ($a) {}

    are exempt from warnings (because they care about truth rather than
    definedness). Operators such as "++", "--", "+=", "-=", and ".=",
    that operate on undefined left values such as:

    my $a;
    $a++;

    are also always exempt from such warnings.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    I would put it as: A Boolean context is a scalar context, but it does
    not convert values to be either string or a number. Therefore, undef
    in a boolean context evaluates as false without producing a
    uninitialized warning.

    Also, "when used as a reference that isn't being assigned to, it is
    treated as an error" does not appear to be accurate.

    $x = undef;
    if (exists $x->{notdef}) {
    print "Huh?\n";
    }
    printf "after bad ref #3 [%s] [%d] [%s]\n", ref $x,
    scalar keys %{$x}, join(',', keys %{$x});

    produces only

    after bad ref #3 [HASH] [0] []

    That is, it doesn't create a something->{notdef} element, but it does
    assign $x a reference to a new hash, and there's no error or warning.
    I need to go read up on autovivification.

    --
    Tim McDaniel,
    Tim McDaniel, Dec 16, 2011
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. G Kannan
    Replies:
    1
    Views:
    1,223
    Eric J. Roode
    Oct 11, 2003
  2. Sukhbir Dhillon
    Replies:
    1
    Views:
    6,235
    Joe Smith
    Apr 5, 2004
  3. smartins68
    Replies:
    1
    Views:
    5,986
    Joe Smith
    Jun 9, 2004
  4. Liang
    Replies:
    2
    Views:
    751
    Liang
    Aug 11, 2004
  5. Jason
    Replies:
    0
    Views:
    187
    Jason
    Jul 6, 2004
Loading...

Share This Page