Re: When DOESN'T "Use of uninitialized value" show up?
by GrandFather (Saint) on Dec 16, 2011 at 06:43 UTC
|
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
| [reply] [d/l] [select] |
|
|
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->{...}.
| [reply] [d/l] |
|
|
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.
| [reply] [d/l] [select] |
|
|
|
|
|
|
$ 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 => {} }.
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
|
|
|
|
| [reply] [d/l] [select] |
Re: When DOESN'T "Use of uninitialized value" show up?
by Anonymous Monk on Dec 16, 2011 at 08:58 UTC
|
$ perl -le " no autovivification qw/ strict fetch /; my $f; keys @$f;
Reference vivification forbidden at -e line 1.
$ perl -le " no autovivification qw/ warn fetch /; my $f; keys @$f;
Reference was vivified at -e line 1.
| [reply] [d/l] |
Re: When DOESN'T "Use of uninitialized value" show up?
by Tim McDaniel (Novice) on Dec 16, 2011 at 22:41 UTC
|
I hit upon the right search terms somewhere. The crucial pointer was from ambrus of these precincts, in Re: What is true and false in Perl?. He pointed to the perlsyn man page. The current version says, at http://perldoc.perl.org/perlsyn.html#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 believe that "when used as a reference that isn't being assigned to, it is treated as an error" is inaccurate or out of date: autovivification happens and is not an error (unless, I'm told, you use the no autovivification pragma).
Also, I think it's easier to explain boolean as being a scalar context that does not "treat undef as a string or a number", so the fact that it doesn't provoke a warning falls out as a consequence.
| [reply] [d/l] [select] |
|
|
| [reply] |