Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

Re: User of uninitialized value #1512

Closed p5pRT closed 20 years ago

p5pRT commented 24 years ago

Migrated from rt.perl.org#2729 (status was 'resolved')

Searchable as RT2729$

p5pRT commented 24 years ago

From gnat@frii.com

Nicolas MONNET writes​:

my $a = undef; my $b = 'gelp'; $a ne $b and print "fuck"; Use of uninitialized value at - line 3. fuck[nico@​nico nico]$

This warning does'nt make sense. $a is perfectly initialized. The 'undef' value has a meaning. Comparing to it makes sense.

You're right\, "use of uninitialized value" should really be "use of undefined value". The "uninitialized" part comes from the warning's most common manifestation​:

  # $x is never given a value   if ($y eq $x) { print "same" }

Many Perl functions use undef as an error value (e.g.\, \ to read from a filehandle). At runtime\, Perl can't tell the difference between undef resulting from never giving a variable a value\, undef resulting from a function returning undef\, and undef resulting from your writing $x = undef.

And it shouldn't. In all three cases\, you've given a value to a variable that isn't a string. If you use eq to compare an undefined value\, you're doing something wrong. Perl tries to make sense of it by using "" as the string value for undef\, but it's still highly suspicious.

And the POINT of -w is to warn on suspicious things.

HOWEVER\, computing with it does'nt​:

$a = undef; $a++; $a = undef; $c = $a+2; $a = undef; $a .= ' ';

THOSE should all put warnings.

The first and last do not print a warning because ++ is special-cased to avoid warnings. It's a pain in the butt to have to keep saying "have I seen this thing before? If not\, initialize it". So ++ doesn't give uninitialized value warnings. It's designed for loops like this​:   while (\<>) {   $seen{$_}++;   }

The middle one *does* emit a warning. You're treating undef like a number\, and it's not a number. If you use ++\, or += or .= or any of the operators that modify their LHS\, you won't get the warning. Any other use of undef as though it were a string or a number will emit warnings.

In 5.6\, warnings are customisable. You can turn off individual warnings for a region or the entire program with the "warnings" pragma​:

  use warnings;   { no warnings "initialized";   if ($x eq $y) { ... }   }

but I remind you that almost every use of undef as though it were a string is wrong wrong wrong.

However\, it's probably way too late to change the name of uninitialized value\, as people may have written code that expects to ignore these warnings.

Nat

p5pRT commented 24 years ago

From [Unknown Contact. See original ticket]

On Mon\, 27 Mar 2000\, Nathan Torkington wrote​:

You're right\, "use of uninitialized value" should really be "use of undefined value". The "uninitialized" part comes from the warning's most common manifestation​:
# $x is never given a value
if ($y eq $x) { print "same" }

I don't know the perl internals well enough\, HOWEVER\, should'nt it be that this kind of warning be issued when a new variable is created in memory as an r-value?

Example​:

$a = 'sumthin'; $test = undef; # here a new variable is created in memory if ($a eq $test) { }

... should be fine ...

but

$a = 'sumthin'; $test = 'sumthinelse'; if ($a eq $tset) { } #speling error causing a new variable to   # be instantiated\, likely to be an error

... should output a warning\, should'nt it?

|but I remind you that almost every use of undef as though it were |a string is wrong wrong wrong.

Case in point​: DBI returns undef for SQL NULL. Say you want to see if the cell is equal to some special value​: $cell = ($sth->fetchrow_array)[0]; if ($cell eq 'specialvalue') {   print "specialvalue"; }

In this case\, you don't care if $cell is undef or not. I fail to see how\, in a comparison\, it may lead to any kind of problem (I can be wrong). However\, using the value as if it was a string\, as implied\, for example by​: $a = $cell." is the value."; should yield a warning.

Note​: I'm not trying to have Perl's behavior changed\, just to point out why warnings are a pain in the ass and why I don't use them most of the time. Adding tests for definedness in that type of cases is much much more trouble than the few occasions where I misspelled a variable name that ended up throwing a warning.

|However\, it's probably way too late to change the name of |uninitialized value\, as people may have written code that expects |to ignore these warnings.