--- name: splice signature: 'splice ARRAY, OFFSET, LENGTH, LIST' signatures: - 'splice ARRAY' - 'splice ARRAY, OFFSET' - 'splice ARRAY, OFFSET, LENGTH' - 'splice ARRAY, OFFSET, LENGTH, LIST' since: 5.0 status: documented categories: ["Arrays"] --- ```{index} single: splice; Perl built-in ``` *[Arrays](../perlfunc-by-category)* # splice Remove and/or replace a slice of an array in place, and return the removed elements. `splice` is the general-purpose array surgeon. Every other array mutator — [`push`](push), [`pop`](pop), [`shift`](shift), [`unshift`](unshift), single-element assignment — can be written as a `splice` call. Pick the position with `OFFSET`, pick how many elements to cut with `LENGTH`, and optionally supply a `LIST` of replacements. The array grows or shrinks to fit, and you get back whatever was cut out. ## Synopsis ```perl splice @array; # remove everything splice @array, $offset; # remove from $offset to the end splice @array, $offset, $length; # remove $length elements splice @array, $offset, $length, @list; # remove and replace with @list ``` ## What you get back - **List context**: the list of elements that were removed, in their original order. Empty list if nothing was removed. - **Scalar context**: the *last* element removed, or [`undef`](undef) if nothing was removed. This is rarely what you want — reach for list context unless you specifically need only the tail. - **Void context**: nothing; use this form when you only care about the in-place mutation. ## Examples Basic removal — cut two elements starting at index 1: ```perl my @a = ('a', 'b', 'c', 'd', 'e'); my @gone = splice @a, 1, 2; # @a == ('a', 'd', 'e') # @gone == ('b', 'c') ``` Insert without removing — `LENGTH` is `0`, so nothing comes out and the `LIST` is spliced in at `OFFSET`: ```perl my @a = (1, 2, 5, 6); splice @a, 2, 0, 3, 4; # @a == (1, 2, 3, 4, 5, 6) ``` Replace a fragment — `LENGTH` and replacement size need not match. Here three elements leave, one arrives: ```perl my @a = ('x', 'y', 'z', 'w', 'v'); my @gone = splice @a, 1, 3, 'Y'; # @a == ('x', 'Y', 'v') # @gone == ('y', 'z', 'w') ``` Remove the trailing tail — omit `LENGTH` entirely to cut from `OFFSET` to the end: ```perl my @a = (1, 2, 3, 4, 5); my @tail = splice @a, 3; # @a == (1, 2, 3) # @tail == (4, 5) ``` Negative `OFFSET` counts from the end. Pop the last element: ```perl my @a = ('a', 'b', 'c'); my $last = splice @a, -1; # @a == ('a', 'b') # $last == 'c' ``` Classic idiom — consume an array `$n` elements at a time: ```perl while (my @chunk = splice @queue, 0, $n) { process(@chunk); } ``` All the common array primitives written as `splice` (assuming `$#a >= $i`): ```perl push @a, $x, $y; # splice @a, scalar(@a), 0, $x, $y pop @a; # splice @a, -1 shift @a; # splice @a, 0, 1 unshift @a, $x, $y; # splice @a, 0, 0, $x, $y $a[$i] = $y; # splice @a, $i, 1, $y ``` ## Edge cases - **Negative `OFFSET`** counts from the end: `-1` is the last element, `-2` the one before, and so on. If the magnitude exceeds the array length, Perl issues a warning and clamps to `0`. - **Negative `LENGTH`** leaves that many elements at the end of the array untouched. `splice @a, 2, -1` removes from index `2` up to but not including the final element. - **`OFFSET` past the end**: with an explicit `LENGTH`, Perl issues a warning and splices at the end of the array (equivalent to `splice @a, scalar(@a), 0, LIST`). Without a `LENGTH`, nothing is removed. - **`LENGTH` past the end**: silently clamped. `splice @a, 1, 999` simply removes everything from index `1` onward. - **Both `OFFSET` and `LENGTH` omitted**: removes every element. The array is left empty. - **Replacement list size differs from `LENGTH`**: the array grows or shrinks to match. There is no requirement that `scalar(@list)` equal `LENGTH` — that asymmetry is the whole point of `splice`. - **Array reference**: dereference inline. `splice @$ref, 0, 1` and `splice @{ $obj->{items} }, -2` both work. - **Splicing a slice is not supported**: `splice @a[1..3], 0, 1` is a syntax error. `splice` requires a named array or dereferenced array, not a list expression. To operate on a range, pass the bounds as `OFFSET` and `LENGTH` instead. - **Void context is fine**. If the return value is not needed, call `splice` as a statement — no allocation of the removed-elements list happens in that case. - **Scalar expressions as the first argument**: not allowed. An experimental feature permitted this from 5.14 through 5.22 and was removed in 5.24. The first argument must be an array (or dereferenced arrayref). ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`push`](push) — append to the end; equivalent to `splice @a, scalar(@a), 0, LIST` - [`pop`](pop) — remove the last element; equivalent to `splice @a, -1` - [`shift`](shift) — remove the first element; equivalent to `splice @a, 0, 1` - [`unshift`](unshift) — prepend; equivalent to `splice @a, 0, 0, LIST` - [`delete`](delete) — superficially similar but semantically different. `delete $a[$i]` leaves a hole (the slot becomes [`undef`](undef)) and does **not** renumber later indices; the array's length is unchanged unless the deleted slot was the last one. `splice @a, $i, 1` physically removes the slot and shifts every later element down by one. Use [`delete`](delete) for sparse arrays where index identity matters; use `splice` when you want the array to close up. - [`grep`](grep) — filter an array into a new one by predicate; reach for it instead of `splice` when you want "keep only the ones that match" rather than "cut out a contiguous range"