Perl References and Advanced Data Structures


Sparse N-dimensional matrix

If you have a situation where you need a large sparsely populated N-dimensional matrix, then a very good and easy way is to use a hash, even if a hash is a "flat" data structure. The secret is in constructing an appropiate key. An example could be a three dimensional matrix which could be populated in this way:
$matrix{"$x,$y,$z"} = $value;
Every time you wanted to use a value from the matrix, you can access it like this:
$value = exists $matrix{"$x,$y,$z"} ? $matrix{"$x,$y,$z"} : 0;
Notice that $x, $y, $z is not limited to numbers, they could be SwissProt IDs.

References

A reference is much like a pointer in other languages. A "normal" variable holds some data, a reference is a variable that refers/points to the location of the data in memory. This is similar to the way your address refers to the place you live, but it does not contain your actual home.
You create references with the backslash operator. Examples:
$variablereference = \$variable;
$arrayreference = \@array;
$hashreference = \%hash;
$codereference = \&subroutine;
$filereference = \*STDOUT;
You use/dereference the data that your reference points to in this way.
print ${$variablereference};
${$arrayreference}[0] = 1;
print ${$arrayreference}[0];
@tab = @{$arrayreference};
${$hashreference}{'alpha'} = 1;
print ${$hashreference}{'alpha'};
%hash = %{$hashreference};
&{$codereference}('parameter');
print $filereference $data;
$data = <$filereference>
If you want to use a shorter notation then you can omit the braces {} around the reference like this:
print $$hashreference{'alpha'};
It is also possible (and recommended) to use the infix operator -> on arrays, hashes and subroutines. The examples below are just different syntactical ways to express the same thing.
$$hashref{$key} = 'blabla';
${$hashref}{$key} = 'blabla';
$hashref->{$key} = 'blabla';
Simple references are especially good to use if you want to call subroutines with more than one array/hash as parameter. Actually it is the only way to do so.

Table of array/hash syntax with and without references.

my @array = (1, 2, 3);
my @hash = (one => 1, two => 2, three => 3);
my $aref = \@array;
my $href = \%hash;

NORMAL		REFERENCE
@array		@{$aref}
$array[1]	${$aref}[0]
$#array		$#{$aref}
%hash		%{$href}
$hash{key}	${$href}{key} 

If you have a variable and you are unsure if it is a reference or not, then you can use the ref function to test it. ref returns false if it is a normal variable.

if (ref $hashreference) {
   print "This is a reference\n";
}
else {
   print "This is a normal variable\n";
}
If the variable tested is really a reference, then the type of reference is returned by ref.
if (ref $reference eq 'SCALAR') {
   print "This is a reference to a scalar (variable)\n";
}
elsif (ref $reference eq 'ARRAY') {  
   print "This is a reference to an array\n";
}
elsif (ref $reference eq 'HASH') {  
   print "This is a reference to a hash\n";
}
elsif (ref $reference eq 'CODE') {  
   print "This is a reference to a subroutine\n";
}
elsif (ref $reference eq 'REF') {  
   print "This is a reference to another reference\n";
}
There are a few other possibilites, but they are seldom used.

This page was last updated         by Peter Wad Sackett, pws@cbs.dtu.dk