This and other RFCs are available on the web at
http://dev.perl.org/rfc/
=head1 TITLE
Optional 2nd argument to C<pop()> and C<shift()>
=head1 VERSION
Maintainer: Jonathan Scott Duff <[EMAIL PROTECTED]>
Date: 7 Aug 2000
Last-Modified: 1 Sep 2000
Version: 3
Mailing List: [EMAIL PROTECTED]
Number: 56
Status: Developing
=head1 ABSTRACT
The inverse operations to C<pop()> and C<shift()> both accept a LIST to
"add" to an array, yet C<pop()> and C<shift()> only remove B<one> element
from an array. In the interest of symmetry and TMTOWTDI, C<pop()> and
C<shift> should allow the programmer to remove multiple items from an
array.
=head1 DESCRIPTION
The intent should be obvious, but I'll point it out anyway.
=head2 pop
The documentation for Perl 5.6.0 states that pop has one of two forms:
C<pop ARRAY>, or just C<pop>. This RFC proposes that a third form be
added to C<pop()>
=over 4
=item pop ARRAY, EXPR
EXPR would be evaluated to determine the number of elements to remove
from the end of ARRAY and that number would be removed and returned.
Thus C<pop()> would be a more natural inverse to C<push()> (If you can
add multiple elements to an array with C<push()>, why can't you remove
multiple elements from an array with C<pop>?)
=back
This functionality can currently be accomplished with C<splice()>, but
it is non-obvious that C<splice()> should be the routine to call and
the method isn't at all intuitive. To "pop" the last $N items off of
the end of an array using C<splice()>, the call looks like this:
splice @array, -$N; # remove the last $N items
contrast to the more natural looking
pop @array, $N; # remove the last $N items
Aaron J Mackey <[EMAIL PROTECTED]> asked whether or not this should
really be equivalent to:
reverse splice @b, -$N; # As if we'd popped each individually
I think that the following should hold:
@a = pop @b, $n;
push @b, @a; # @b now in its original state.
Thus, the 2 argument version of C<pop()> should treat the C<$N>
elements as a group.
=head2 shift
The semantics for C<shift()> are similar to C<pop()> except that it
operates on the other end of the array. C<shift()> also suffers from
the inability to shift more than one element from the array. Just
like C<pop()>, the two forms of C<shift()> are a C<shift ARRAY>, and
just plain C<shift>. This RFC proposes that a third form be added:
=over 4
=item shift ARRAY, EXPR
EXPR would be evaluated to determine the number of elements to remove
from the beginning of ARRAY and that number would be removed and returned.
Thus, C<shift()> would be a more natural inverse to C<unshift>. (If
you can add multiple elements to an array with C<unshift()>, why can't
you remove multiple elements with C<shift()>?)
=back
As with C<pop()> the proposed semantics can be accomplished with
C<splice()> and are just as un-intuitive:
splice @array, 0, $N; # remove the first $N elements
contrast to
shift @array, $N; # remove the first $N elements
Again, as with C<pop()>, C<shift()> should treat the first $N elements
of the C<@array> as a group so that the following holds:
@a = shift @b, $N; # remove the first $N elements
unshift @b, @a; # put them back
# @b is unchanged
=head2 Random examples
@numbers = 1..10;
$ten = pop @numbers; # still works
@popped = pop @numbers, 3; # Take away 7, 8, 9
push @numbers, @popped; # Put 'em back
@popped = pop @numbers, 0; # Nothing happens
@popped = pop @numbers, 9; # And then there were none.
@numbers = 1..10;
@popped = pop @numbers, 100; # And then there were none but
# @popped only has 10 things
@numbers = 1..10;
$one = shift @numbers; # still works
@shifted = shift @numbers, 3; # Take away 2, 3, and 4
unshift @numbers, @shifted; # Put 'em back
@shifted = shift @numbers, 0; # Nothing happens
@shifted = shift @numbers, 9; # And then there were none.
@numbers = 1..10;
@shifted = shift @numbers, 100; # And then there were none but
# @shifted only has 10 things
=head1 IMPLEMENTATION
I don't know the gory details other than it should be possible.
However, there is one implementation detail that occurs to me:
What should happen when the expression given to C<pop()>, or
C<shift()> evaluates to a negative number? I see three options:
1) Nothing. We can only pop/shift positive amounts
2) Act as if the number were positive (i.e. pop @array, abs(EXPR))
3) C<pop()> would then act as C<shift()> and C<shift()> would
act as C<pop()>
I propose that option #3 be adopted since it seems the most Perlian
and so far no one has disagreed. :-)
=head1 MIGRATION
Gisle Aas <[EMAIL PROTECTED]> mentioned that the behavior of code
such as this:
foo(pop @a, "bar");
would be changed by this proposal and that the perl5 to perl6
converter would need to handle this case. Similar provisions would
need to be made for the proposed 2-argument C<shift()>
=head1 ISSUES
Several people have commented on the proposed return values for the
new forms of C<shift> and C<pop>. The author of this RFC continues to
maintain that the following identities should hold:
push(@array, pop(@array, $N)); # @array is unchanged
unshift(@array, shift(@array, $N)); # @array is unchanged
=head1 REFERENCES
The Perl 5.6.0 documentation
L<perlfunc/pop>
L<perlfunc/shift>
L<perlfunc/splice>
Comments on return values
http://www.mail-archive.com/perl6-language@perl.org/msg01306.html
http://www.mail-archive.com/perl6-language@perl.org/msg02465.html
Perl5 -> Perl6 translation issues
http://www.mail-archive.com/perl6-language@perl.org/msg01328.html