th3penguinwhisperer
th3penguinwhisperer

Reputation: 466

Passing an array to a subroutine encloses it in another array?

I noticed that when I pass an array to my subroutine it seems like it gets encapsulated by another array (so two levels, while the initial is only one).

I know that using references to arrays is better, but I'm wondering in this specific case why it is not working as expected.

Code example:

#!/usr/local/bin/perl

use Data::Dumper;

sub testSub {
    my (@arr) = (@_);
    print Dumper \@arr;
}

my @testArray = ();
push @testArray, {
    'key1' => 'value1',
    'key2' => 'value2',
    'urls' => [ 'www.example.com' ]
};

print Dumper @testArray;

foreach my $item ( @testArray ) {

    my @urls = testSub( $item->{'urls'} );
}

output

$VAR1 = {
          'urls' => [
                      'www.example.com'
                    ],
          'key1' => 'value1',
          'key2' => 'value2'
        };
$VAR1 = [
          [
            'www.example.com'
          ]
        ];

Upvotes: 0

Views: 61

Answers (3)

dolmen
dolmen

Reputation: 8706

If you want testSub to receive a list of URLs, you must expand the array $item->{urls} into a list with @{ ... }:

my @urls = testSub( @{ $item->{'urls'} } );

Upvotes: 0

Mike
Mike

Reputation: 2005

my @urls = testSub( $item->{'urls'}, 'abc' );

Result of Dumper in subrotine:
$VAR1 = [
          [
            'www.example.com'
          ],
          'abc'
        ];

Array passed by reference. Since at the time of compilation perl did not know what will be in the scalar $item->{'urls'}.

my @urls = testSub( @{ $item->{'urls'} }, 'abc' );

Result of Dumper in subrotine:
$VAR1 = [
          'www.example.com',
          'abc'
        ];

Now the compiler expects an array and turns it into a list.

Upvotes: 1

Borodin
Borodin

Reputation: 126722

  • You are passing $item->{'urls'} to your subroutine

  • Your Data::Dumper output clearly shows that the hash element looks like this

    'urls' => [ 'www.example.com' ]
    
  • When you call testSub, you are making an assignment that is equivalent to

    my @arr = ( [ 'www.example.com' ] );
    
  • Your statement print Dumper \@arr passes an array reference to Dumper, so it displays

    [ [ 'www.example.com' ] ]
    

It would help your confusion if you were consistent in calling Dumper. print Dumper @testArray passes the contents of @testArray as individual parameters (although in this case the array has only a single element) while print Dumper \@arr passes an array reference as a single parameter, and is the better choice

Upvotes: 1

Related Questions