Given an array called @names = qw(Foo Bar Baz); and another array called my @languages = qw(Perl Python Ruby PHP); how can the @languages array be inserted in the "middle" of the @names array?

Of course I think the "middle" only means - "somewhere" and not that "the same distance from the beginning and from the end", but we have another issue with the task.

There can be two types of insertions. Flattening, when the elements of @language become elements of @names, and thus at the end of the operation @names will have 7 elements; or it can be non-flattening, that will create a sort-of two-dimensional array. In this case @names will have 4 elements after the operation, one of them is a reference to an internal array that holds the elements of @languages.

The solution to the two cases is quite similar. They both use the splice function. Maybe we just need to adjust how we call the operation:

In the first case we

Insert an array in another array

examples/insert_array_in_array.pl

use strict;
use warnings;
use 5.010;
use Data::Dumper;

my @names = qw(Foo Bar Baz);
my @languages = qw(Perl Python Ruby PHP);

splice @names, 1, 0, @languages;

print Dumper \@names;

in the second case we

Insert and array reference in another array

examples/insert_array_ref_in_array.pl

use strict;
use warnings;
use 5.010;
use Data::Dumper;

my @names = qw(Foo Bar Baz);
my @languages = qw(Perl Python Ruby PHP);

splice @names, 1, 0, \@languages;

print Dumper \@names;

say $names[1][2];    # Ruby



print Dumper $names[1];

The difference in the two code snippets is that in the first one we insert @languages and in the second one we insert \@languages. Note the leading backslash.

If we run the scripts:

The first one generates a simple, flat array:

$ perl examples/insert_array_in_array.pl 

$VAR1 = [
          'Foo',
          'Perl',
          'Python',
          'Ruby',
          'PHP',
          'Bar',
          'Baz'
        ];

The second one generates a two-dimensional array:

$ perl examples/insert_array_ref_in_array.pl 

$VAR1 = [
          'Foo',
          [
            'Perl',
            'Python',
            'Ruby',
            'PHP'
          ],
          'Bar',
          'Baz'
        ];
Ruby
$VAR1 = [
          'Perl',
          'Python',
          'Ruby',
          'PHP'
        ];

in which we can reach the values of the inserted array by using the the appropriate index on the main array.

Beside one leaving a one-dimensional array behind and the other one creating a two-dimensional array, there is another big difference between the two. What if after inserting the array we change the original @languages array?

Changing the content of the array

In the first case, the content of @languages changes but the content of @names remains the same as it was after the call to splice.

examples/insert_array_in_array_change.pl

use strict;
use warnings;
use 5.010;
use Data::Dumper;

my @names = qw(Foo Bar Baz);
my @languages = qw(Perl Python Ruby PHP);

splice @names, 1, 0, @languages;

print Dumper \@names;

$languages[2] = "JavaScript";

say '';
print Dumper \@languages;
print Dumper \@names;

$ perl examples/insert_array_in_array_change.pl 

$VAR1 = [
          'Foo',
          'Perl',
          'Python',
          'Ruby',
          'PHP',
          'Bar',
          'Baz'
        ];

$VAR1 = [
          'Perl',
          'Python',
          'JavaScript',
          'PHP'
        ];
$VAR1 = [
          'Foo',
          'Perl',
          'Python',
          'Ruby',
          'PHP',
          'Bar',
          'Baz'
        ];

Changing the content of the references array

On the other hand, if we take the case when we inserted a an array reference in the array and created a two dimensional array, then the internal array remains "connected" to the original array. Thus if we change the @languages array (setting element 2 to be JavaScript) this change will be reflected both in @languages and in the internal array of @names. (See JavaScript in the 2 last dumps below)

examples/insert_array_ref_in_array_change.pl

use strict;
use warnings;
use 5.010;
use Data::Dumper;

my @names = qw(Foo Bar Baz);
my @languages = qw(Perl Python Ruby PHP);

splice @names, 1, 0, \@languages;

print Dumper \@names;

say $names[1][2];



print Dumper $names[1];

$languages[2] = "JavaScript";

say '';
print Dumper \@languages;
print Dumper \@names;


perl examples/insert_array_ref_in_array_change.pl 

$VAR1 = [
          'Foo',
          [
            'Perl',
            'Python',
            'Ruby',
            'PHP'
          ],
          'Bar',
          'Baz'
        ];
Ruby
$VAR1 = [
          'Perl',
          'Python',
          'Ruby',
          'PHP'
        ];

$VAR1 = [
          'Perl',
          'Python',
          'JavaScript',
          'PHP'
        ];
$VAR1 = [
          'Foo',
          [
            'Perl',
            'Python',
            'JavaScript',
            'PHP'
          ],
          'Bar',
          'Baz'
        ];

This happens because in the second case we have copied the reference of the array but now both @languages and $names[1] point to the same location in the memory. So if we change the content of either of those, the other one will change too.