in reply to When DOESN'T "Use of uninitialized value" show up?

undef is false by definition in Perl and so is absolutely fine whenever in a boolean context.

Autovivification only happens when required, such as during an assignment (but not for a test). However if a chain of references is required all the intermediate references will autovivify, but not the last item in the chain. Consider:

#!/usr/bin/perl use strict; use warnings; my $x; my $y; if ($y) { } if (! $y) { } if ($y && ! $y) { } if (exists $x->{notdef}) { } if (defined $x->{notdef}) { } if ($x->{notdef}) { } print ref $x, "\n"; print "\$y is undef\n" if ! defined $y; if (exists $x->{notdef}{notdeftoo}) {} print "Now \$x->{notdef} exists\n" if exists $x->{notdef};

Prints:

HASH $y is undef Now $x->{notdef} exists

Note though that $x became a hash ref because it was treated as one even before any autovification took place which makes the dereference ok - $x is no longer undef.

True laziness is hard work

Replies are listed 'Best First'.
Re^2: When DOESN'T "Use of uninitialized value" show up?
by Tim McDaniel (Novice) on Dec 16, 2011 at 07:08 UTC

    undef is false by definition in Perl and so is absolutely fine whenever in a boolean context.

    "By definition" doesn't help explain it. For example, undef is interpreted as 0 by definition in a numeric context, but I nevertheless get "Use of uninitialized value" for 1 + undef.

    perldiag, explaining the message, just says '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.' Since there is no qualifier on "used", I interpreted it to include use in a boolean context. I'd love to know where it might be clarified in documentation.

    Hmm, now looking at it again, maybe the second sentence is the real rule (so the first is a misleading summary): you get the warning if and only if, due to the operation it's being used in, Perl has to convert an undef value to a string ("") or number (0)? If so, I still think that undef->{anything} not causing an error is a bad design, and other uses in an rvalue context might be. Personally, I want it to complain about any use of an undefined value.

    What contexts are there for use of undef? Converting to a string, converting to a string, assignment, boolean, dereferencing via ->, ... any others?

    Sub call?

    $ perl -e 'my $x = undef; &$x("frog")' Undefined subroutine &main:: called at -e line 1.

    I guess that's a conversion to a string instead of a bad reference -- like an eval rather than like undef->{...}.

      you get the warning if and only if, due to the operation it's being used in, Perl has to convert an undef value to a string ("") or number (0)?

      Bingo.

      Addition wants a number. If you don't pass a number, the value gets coerced into a number. Coercions from undef warn.

      A truth test doesn't require or cause coercion, so there's no coercion that can warn.

      What contexts are there for use of undef?

      What does that mean? Are you asking what behaviour an operator can take when passed undef as one of its operand? Well, that's entirely up to the operator.

      Personally, I want it to complain about any use of an undefined value.

      That's so wrong. Paradoxically, making the use of undefined values always warn will have a net *drop* in useful warnings.

      People use undefined values because they know warnings will occur if it's misused. If using undefined values always warns, a different value that never warns will be used instead.

      Not to mention it's silly to have defined($undef), my $x = undef; and my $x = 123; warn.

      You might be interested in no autovivfication;, though.

        Personally, I want it to complain about any use of an undefined value.

        That's so wrong. Paradoxically, making the use of undefined values always warn will have a net *drop* in useful warnings.

        People use undefined values because they know warnings will occur if it's misused. If using undefined values always warns, a different value that never warns will be used instead.

        It's true that having more warnings may turn people off and cause them to turn warnings off. Someone in my office did that right now, and I think it was for no warnings 'uninitialized'.

        Nevertheless, I don't often use uninitialized values as actual values, and when I do, I check for it being !defined before using it further. So I want more restrictions on the use of uninitialized values. I would prefer if all arithmetic on undef values threw a warning, for example, or use in a boolean context.

        Not to mention it's silly to have defined($undef), my $x = undef; and my $x = 123; warn.

        Thank you for pointing out defined(): since it's defined to deal with undef, certainly it should not throw a warning with undef! Similarly with //, and exists is arguably in the same class.

        However, "my $x = undef" is equivalent to "my $x" or even "undef my $x". And I don't consider "my $x = 123;" to use undef at all: in this context, you can't tell that $x was ever assigned undef, and even if it was, that value is never referenced but is instead stomped out of existence.

        In C, the term I'm looking for is "rvalue": I would like warnings whenever I try to access the value of undef.

        Thank you for the pointer to "no autovivification;" I don't know any details about autovivification and I need to look it up.

Re^2: When DOESN'T "Use of uninitialized value" show up?
by moritz (Cardinal) on Dec 16, 2011 at 16:47 UTC
    Autovivification only happens when required

    Be careful with such statements:

    $ perl -le 'my $a; defined $a->{b}{c}; print ref $a' HASH

    Autovivification is not required here, but still the hash access autovivifies $a to { b => {} }.

      Actually that was exactly the case I had in mind when I made the statement. "b => {}" is required so that the presence of {c} can be checked. In fact I updated the OP's sample to include exists $x->{notdef}{notdeftoo} to demonstrate this case.

      True laziness is hard work
        "b => {}" is required so that the presence of {c} can be checked.

        And that's the part where I disagree. If $a->{b} doesn't exist, we know that $a->{b}{c} cannot exist, and perl could know too. The fact that such reads autovivify are really only due to a quirk in the implementation, and not deducible from a general rule like "autovivification happens only when it needs to".

      But that's what Grandfather said: " However if a chain of references is required all the intermediate references will autovivify, but not the last item in the chain " didn't he?

      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e