Where is the uninitialised value in the below code?
#!/usr/bin/perl
use warnings;
my @sites = (undef, "a", "b");
my $sitecount = 1;
my $url;
while (($url = $sites[$sitecount]) ne undef) {
$sitecount++;
}
Output:
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
Use of uninitialized value in string ne at t.pl line 6.
You can't use undef
in a string comparison without a warning.
if ("a" ne undef) { ... }
will raise a warning. If you want to test if a variable is defined or not, use:
if (defined $var) { ... }
Comments about the original question:
That's a strange way to iterate over an array. The more usual way of doing this would be:
foreach my $url (@sites) { ... }
and drop the $sitecount
variable completely, and don't overwrite $url
in the loop body. Also drop the undef
value in that array. If you don't want to remove that undef
for some reason (or expect undefined values to be inserted in there), you could do:
foreach my $url (@sites) {
next unless defined $url;
...
}
If you do want to test for undefined with your form of loop construct, you'd need:
while (defined $sites[$sitecount]) {
my $url = $sites[$sitecount];
...
$sitecount++;
}
to avoid the warnings, but beware of autovivification, and that loop would stop short if you have undef
s mixed in between other live values.
The correct answers have already been given (defined
is how you check a value for definedness), but I wanted to add something.
In perlop you will read this description of ne
:
Binary "ne" returns true if the left argument is stringwise not equal to the right argument.
Note the use of "stringwise". It basically means that just like with other operators, such as ==
, where the argument type is pre-defined, any arguments to ne
will effectively be converted to strings before the operation is performed. This is to accommodate operations such as:
if ($foo == "1002") # string "1002" is converted to a number
if ($foo eq 1002) # number 1002 is converted to a string
Perl has no fixed data types, and relies on conversion of data. In this case, undef
(which coincidentally is not a value, it is a function: undef()
, which returns the undefined value), is converted to a string. This conversion will cause false positives, that may be hard to detect if warnings
is not in effect.
Consider:
perl -e 'print "" eq undef() ? "yes" : "no"'
This will print "yes", even though clearly the empty string ""
is not equal to not defined
. By using warnings
, we can catch this error.
What you want is probably something like:
for my $url (@sites) {
last unless defined $url;
...
}
Or, if you want to skip to a certain array element:
my $start = 1;
for my $index ($start .. $#sites) {
last unless defined $sites[$index];
...
}
Same basic principle, but using an array slice, and avoiding indexes:
my $start = 1;
for my $url (@sites[$start .. $#sites]) {
last unless defined $url;
...
}
Note that the use of last
instead of next
is the logical equivalent of your while loop condition: When an undefined value is encountered, the loop is exited.
More debugging: http://codepad.org/Nb5IwX0Q
If you, like in this paste above, print out the iteration counter and the value, you will quite clearly see when the different warnings appear. You get one warning for the first comparison "a" ne undef
, one for the second, and two for the last. The last warnings come when $sitecount
exceeds the max index of @sites
, and you are comparing two undefined values with ne
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With