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/[email protected]/msg01306.html http://www.mail-archive.com/[email protected]/msg02465.html Perl5 -> Perl6 translation issues http://www.mail-archive.com/[email protected]/msg01328.html
