Home > front end >  Is starting with a Perl hash reference a bad way to build up a data structure?
Is starting with a Perl hash reference a bad way to build up a data structure?

Time:11-16

A colleague wrote some Perl code (v5.30.0) that does all of this:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

package main;

sub processScalarHash
{
        my $bar = $_[0];
        printf "A subroutine can access the scalar hash:  \"%s\"\n", $bar->{'key3'};
}

# Build the "Scalar Hash":
my $scalarHash = {};
$scalarHash->{'key1'} = 'dog';
$scalarHash->{'key2'} = 'cat';
$scalarHash->{'key3'} = 'fish';
bless $scalarHash;

printf "I can examine the scalar hash:\n";
print Dumper(\$scalarHash);

printf "I can access the scalar hash:  \"%s\"\n", $scalarHash->{'key1'};
my $tmpStr = 'key2';
printf "I can access the scalar hash:  \"%s\"\n", $scalarHash->{$tmpStr};

processScalarHash($scalarHash);

Output is:

me@ubuntu01$ ./ScalarHash.perl
I can examine the scalar hash:
$VAR1 = \bless( {
                   'key3' => 'fish',
                   'key1' => 'dog',
                   'key2' => 'cat'
                 }, 'main' );
I can access the scalar hash:  "dog"
I can access the scalar hash:  "cat"
A subroutine can access the scalar hash:  "fish"
me@ubuntu01$

I'm just learning Perl myself, and what strikes me here is that I never see any documentation about referencing hashes with scalar ($) variables. With hash (%) and array (@) variables, yes, but never scalars ($)! I don't know why my colleague coded like this, but I have a sinking feeling that using "scalar hashes" is a very bad practice.

Asking as a Perl newbie: Is this bad coding? The last thing I want to do is perpetuate bad habits that could bite me later.

CodePudding user response:

It is not particularly bad.


Consider this:

sub f {
   my $h = shift;                   # Ref to hash
   for my $k ( keys( %$h ) ) {
      say "$k: $h->{ $k }";
   }
}

my %h = ( a => 123, b => 456 );     # Hash
$h{ c } = 789;
f( \%h );

One can't pass a hash to a sub. But one can pass a reference to a hash to a sub. So we're often working with hashes through a reference.

You're asking if it's ok to do work with hashes through a reference even it's not required.

sub f {
   my $h = shift;                   # Ref to hash
   for my $k ( keys( %$h ) ) {
      say "$k: $h->{ $k }";
   }
}

my $h = { a => 123, b => 456 };     # Ref to anon hash
$h->{ c } = 789;
f( $h );

There's a performance penalty, but it's surely microscopic. The only real downside is that it makes the code noisier. But not so much that it can't be overlooked. If that's ok, then absolutely go ahead and use this style.


That bless doesn't belong there, though. A bless outside of a constructor and blessing into main are both things to be avoided.

CodePudding user response:

Side note that won't fit in a comment: When building hashes, I try to minimize the amount of repeated code by building the hash all at once.

my $hash_reference = {
    key1 => 'dog',
    key2 => 'cat',
    key3 => 'fish',
};

instead of

my $scalarHash = {};
$scalarHash->{'key1'} = 'dog';
$scalarHash->{'key2'} = 'cat';
$scalarHash->{'key3'} = 'fish';
  • Related