Search code examples
arraysperlreferencehashmap

Why does a reference to an array change to a hash reference when passed to a subroutine


I came across this issue in a tool I'm attempting to fix and don't understand what causes the array reference change to a hash reference. It only occurs when the array ref is listed after the hash ref in the parameters, which makes me think it's due the way the parameters are received.

I don't have the code from the tool but the below code recreates what was happening.

use strict;
use warnings;

sub PassArrRef{
    my @array = [0,1,2,3,4];
    my %hash = {0,'a',1,'b',2,'c'};
    RecieveHashRef(\%hash, \@array)
}

sub RecieveHashRef{
    my %hash = %{$_[0]};
    my $arrayref = shift;
    print $arrayref;
}

PassArrRef();

This code outputs a Hash reference.


Solution

  • It is because in ReceiveHashRef you are directly referencing the first positional parameter, $_[0] and then on the next line calling shift which takes the first element of the positional parameters. The same thing.

    The typical way to consume the subroutine arguments would be:

    my($hashref, $arrayref) = @_;
    

    Totally fixed, your code should look like this. The diagnostics pragma will give you much more expansive explanations of errors.

    use strict;
    use warnings;
    use diagnostics;
    
    sub PassArrRef{
        my @array = (0,1,2,3,4);
        my %hash = (0,'a',1,'b',2,'c');
        ReceiveHashRef(\%hash, \@array)
    }
    
    sub ReceiveHashRef{
        my($hashref, $arrayref) = @_;
        print "hash ref: $hashref, array ref: $arrayref\n";
    }
    
    PassArrRef();
    

    And make liberal use of https://perldoc.perl.org/!