=begin pod

=TITLE class Array

=SUBTITLE Sequence of itemized values

    class Array is List {}

An C<Array> is a L<List> which forces all its elements to be
scalar containers, which means you can assign to array elements.

=head1 Methods

=head2 routine pop

Defined as:

    multi sub    pop(Array:D )
    multi method pop(Array:D:)

Removes and returns the last item from the array.  Fails for an empty array.

Example:

    my @foo = <a b>; # a b
    @foo.pop;        # b
    pop @foo;        # a
    pop @foo;
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::Cannot::Empty: Cannot pop from an empty Array␤»

=head2 routine push

Defined as:

    multi sub    push(Array:D, **@values) returns Array:D
    multi method push(Array:D: **@values) returns Array:D

Adds the C<@values> to the end of the array, and returns the modified list.
Fails for infinite arrays.

Example:

    my @foo = <a b c>;
    @foo.push: 'd';
    say @foo;                   # [a b c d]

Note that C<push> does not attempt to flatten its argument list.  If you pass
an array or list as the thing to push, it becomes one additional element:

    my @a = <a b c>;
    my @b = <d e f>;
    @a.push: @b;
    say @a.elems;               # 4
    say @a[3].join;             # def

Only if you supply multiple values as separate arguments to C<push> are
multiple values added to the array:

   my @a = '1';
   my @b = <a b>;
   my @c = <E F>;
   @a.push: @b, @c;
   say @a.elems;                # 3

See L<method append|#method append> for when you want to append multiple
values that are stored in a single array.

=head2 method append

Defined as

=begin code :skip-test
sub append(\array, elems)
=end code
    multi method append(Array:D: \values)
    multi method append(Array:D: **@values is raw)

Appends the argument list to the array passed as the first argument.  This
modifies the array in-place.  Returns the modified array.

The difference from method C<push> is that with an array or list argument,
C<append> appends several elements (one for each array or list element),
whereas C<push> appends just one element.

Example:

    my @a = <a b c>;
    my @b = <d e f>;
    @a.append: @b;
    say @a.elems;               # 6
    say @a;                     # [a b c d e f]

=head2 routine shift

Defined as:

    multi sub    shift(Array:D )
    multi method shift(Array:D:)

Removes and returns the first item from the array.  Fails for an empty arrays.

Example:

    my @foo = <a b>;
    say @foo.shift;             # a
    say @foo.shift;             # b
    say @foo.shift;
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::Cannot::Empty: Cannot shift from an empty Array␤»

=head2 routine unshift

Defined as:

    multi sub    unshift(Array:D, **@values) returns Array:D
    multi method unshift(Array:D: **@values) returns Array:D

Adds the C<@values> to the start of the array, and returns the modified array.
Fails if C<@values> is infinite.

Example:

    my @foo = <a b c>;
    @foo.unshift: 1, 3 ... 11;
    say @foo;                   # [(1 3 5 7 9 11) a b c]

The notes in L<the documentation for method push|#method push> apply,
regarding how many elements are added to the array.

L<#method prepend> is the equivalent for adding multiple elements from one
list or array.

=head2 method prepend

Defined as

=begin code :skip-test
sub prepend(\array, elems)
=end code
    multi method prepend(Array:D: \values)
    multi method prepend(Array:D: **@values is raw)

Adds the elements from C<LIST> to the front of the array, modifying it
in-place.

Example:

    my @foo = <a b c>;
    @foo.prepend: 1, 3 ... 11;
    say @foo;                   # [1 3 5 7 9 11 a b c]

=head2 routine splice

Defined as:

    multi sub    splice(@list,  $start, $elems?, *@replacement) returns Array
    multi method splice(Array:D $start, $elems?, *@replacement) returns Array

Deletes C<$elems> elements starting from index C<$start> from the C<Array>,
returns them and replaces them by C<@replacement>.  If C<$elems> is omitted,
all the elements starting from index C<$start> are deleted.

Example:

    my @foo = <a b c d e f g>;
    say @foo.splice(2, 3, <M N O P>);        # [c d e]
    say @foo;                                # [a b M N O P f g]

=head2 method shape

Defined as:

    method shape() { (*,) }

Returns the shape of the array as a list.

Example:

    my @foo[2;3] = ( < 1 2 3 >, < 4 5 6 > ); # Array with fixed dimensions
    say @foo.shape;                          # (2 3)
    my @bar = ( < 1 2 3 >, < 4 5 6 > );      # Normal array (of arrays)
    say @bar.shape;                          # (*)

=head2 method default

Defined as:

    method default

Returns the default value of the invocant, i.e. the value which is returned
when trying to access an element in the C<Array> which has not been
previously initialized or when accessing an element which has explicitly
been set to C<Nil>. Unless the C<Array> is declared as having a default
value by using the L<is default|/routine/is default> trait the method returns
the type object C<(Any)>.

    my @a1 = 1, "two", 2.718;
    say @a1.default;                                       # (Any)
    say @a1[4];                                            # (Any)

    my @a2 is default(17) = 1, "two", 3;
    say @a2.default;                                       # 17
    say @a2[4];                                            # 17
    @a2[1] = Nil;                                          # (resets element to its default)
    say @a2[1];                                            # 17

=head2 method of

Defined as:

    method of

Returns the type constraint for the values of the invocant. By default,
i.e. if no type constraint is given during declaration, the method
returns C<(Mu)>.

    my @a1 = 1, 'two', 3.14159;              # (no type constraint specified)
    say @a1.of;                              # (Mu)

    my Int @a2 = 1, 2, 3;                    # (values must be of type Int)
    say @a2.of;                              # (Int)
    @a2.push: 'd';
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to @a2; expected Int but got Str ("d")␤»

=end pod
