Basic References (Pointers)
#!/usr/bin/perl -w

#########################  Elementary Reference Demo  ########################

#  Parameter passing.  Arrays and hashes should generally be passed to
#  subs by REFERENCE so that only an ADDRESS is copied and not entire
#  arrays/hashes which can be quite large!  When passing multiple 
#  arrays/hashes, passing by reference is necessary so that the arrays
#  or hashes keep their separate identities in memory!

@L1 = (1,3,5);
@L2 = (2,4,6);

swap(\@L1, \@L2);
foreach (@L1) {print "$_\n"}   #  Output 1
print "\n";
foreach (@L2) {print "$_\n"}   #  Output 2
print "\n";


sub swap
{
     my ($rl1, $rl2) = @_;
     my (@temp);

     @temp = @$rl1;
     @$rl1 = @$rl2;
     @$rl2 = @temp;
} 
     

#  Making a list in a sub and passing it back by reference. 

$listref = make_list();
foreach (@$listref) {print "$_\n"}   #  Output 3

sub make_list
{
     my ($listref) = [];   #  Reference to an anonymous, empty list.

     push(@$listref, 1..5);
     return $listref;
} 


#  Using the -> operator when referencing one element of a list.

@L1 = (1,3,5,9,7);
@L2 = (4,2,6,8,9);
$dot_product = dot_product(\@L1, \@L2);
print "Dot product = $dot_product\n\n";
sub dot_product
{
     my ($rl1, $rl2) = @_;
     my ($product) = (0);

     return 0 if @$rl1 != @$rl2;   #  Lengths of arrays must be the same!!
     for (my $i = 0; $i < @$rl1; $i++)
     {
          $product += $rl1->[$i] * $rl2->[$i];   #  -> gets a scalar!!
     }
     return $product;
}


#  Passing hashes by reference and accessing their elements.

%H1 = qw(a 1  b 2  c 3  d 4);
%H2 = qw(c 7  d 8  f 5  h 7);

add_values_of_common_keys_to_H1(\%H1, \%H2);
foreach $key (sort keys %H1)    #  Output 4
{
    print "$key: $H1{$key}\n";  #  c value should now be 10 and d should be 12!
}
print "\n";


sub add_values_of_common_keys_to_H1
{
    my ($rh1, $rh2) = @_;
    my ($key);

    foreach $key (keys %$rh1)
    {
        $rh1->{$key} += $rh2->{$key} if exists $rh2->{$key};
    }
}



#  Creating a hash in a sub and passing it back by reference.

$hashref = make_hash();
foreach $key (sort keys %$hashref)
{
     print "$key: $hashref->{$key}\n";    #  Output 5
}


sub make_hash
{
     my ($hashref) = {};   #  {} is reference to an anonymous hash.

     foreach ('A'..'E')
     {
         $hashref->{$_} = ord($_);
     }
     return $hashref;
} 
#################################  Program Output  ############################

2    #  Output 1
4
6

1    #  Output 2
3
5

1    #  Output 3
2
3
4
5

Dot product = 175

a: 1    #  Output 4
b: 2
c: 10
d: 12

A: 65   #  Output 5
B: 66
C: 67
D: 68
E: 69

########################  List of Reference Parameters  #####################
#!/usr/bin/perl -w

@L1 = qw(1 2 3 4 5);   @L2 = qw(2 4 6 8 10);
@L3 = qw(1 3 5 7 9);   @L4 = qw(5 4 3 2 1);

output_rows(\@L1, \@L2, \@L3, \@L4);    #  List of list references!

sub output_rows
{
    my (@ListOfListRefs) = @_;   #  Works for any number of references!
    my ($ref);

    foreach $ref (@ListOfListRefs) {print "@$ref\n"}
}


%H1 = qw(1 2 3 4);     %H2 = qw(2 4 6 8 9 7);     %H3 = qw(1 3 5 7);

dump_keys(\%H1, \%H2, \%H3);   #  List of hash references!!

sub dump_keys
{
    my (@ListOfHashRefs) = @_;    #  Works for any number of references!!
    my ($ref);

    $, = " ";   #  Dumps unquoted lists with space between elements!
    foreach $ref (@ListOfHashRefs) {print keys(%$ref), "\n"}
}
################################  Output Below  #############################

1 2 3 4 5     #  Dump of list of lists.
2 4 6 8 10
1 3 5 7 9
5 4 3 2 1

1 3           #  Dump of list of hash. 
9 2 6 
1 5