So Im learning Perl and got to the chapter about hashes. I understand that the '=>' operator is an alias to the comma operator. But when I try to make a value undef I get the warning
Use of uninitialized value $last_name{"dino"} in concatenation (.) or string at ./learning.pl line 18.
use warnings;
use strict;
my %last_name = (
fred => 'flintston',
dino => undef,
barney => 'rubble',
betty => 'rubble',
);
my $key;
my $value;
if(%last_name) {
foreach $key (sort keys %last_name) {
print("$key => $last_name{$key}\n");
}
}
But when I change the hash line to:
my %last_name = (
fred => 'flintston',
dino => undef =>
barney => 'rubble',
betty => 'rubble',
);
It works just fine and returns the value as undef. All I did was replace the comma operator separating the key/value with the '=>' operator.
Why does the later work but not the former if the two operators are supposed to be the same?
They are not exactly the same. The "fat comma" does one more thing: it quotes the left hand side operand when it's a bareword. Therefore,
undef, 1
is equivalent to
undef(), 1
while
undef => 1
is equivalent to
'undef', 1
See perlop:
The => operator is a synonym for the comma except that it causes a word on its left to be interpreted as a string if it begins with a letter or underscore and is composed only of letters, digits and underscores.
Choroba has already answered, but I think it can be useful to expand on this a little.
In the first case, when you get a warning, it's because you are printing an undef
value: the value of the key 'dino'
is undefined. Note that when you set the values of the hash you don't get any warning, because giving an undefined value to a key is perfectly normal. The warning shows up only when you try to use this undefined value; it would be better to check it before you use it, like this:
if (defined $last_name{$key}) {
print("$key => $last_name{$key}\n");
}
This way you can avoid the warning.
The interesting part comes in your second case. To understand what happens, you can run this code at the end:
if (defined $last_name{'dino'}) {
print "last_name{'dino'} is defined, and its value is $last_name{'dino'}\n";
if ($last_name{'dino'} =~ /^[u][n][d][e][f]$/) {
print "It matches, which means that the value of last_name{'dino'} " .
"is not undefined, it's the string 'undef'\n";
}
}
and both if
are true, which indicates that the value for $last_name{'dino'}
is defined, and it's the string 'undef'. Of course it's confusing, but it is defined. Therefore, you don't get any warning.
All of this is a way to see what is happening. To understand why, please check choroba's answer.
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