Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl - Hash and the => operator

Tags:

hash

perl

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?

like image 824
Brandon Ess Avatar asked Dec 02 '22 14:12

Brandon Ess


2 Answers

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.

like image 83
choroba Avatar answered Dec 05 '22 22:12

choroba


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.

like image 41
Fabio says Reinstate Monica Avatar answered Dec 05 '22 22:12

Fabio says Reinstate Monica