Negative LENGTH argument to splice
Gisle Aas [Wed, 24 Jun 1998 15:11:35 +0000 (17:11 +0200)]
Message-ID: <m3g1gvc5bs.fsf@furu.g.aas.no>

p4raw-id: //depot/perl@1237

MANIFEST
pod/perlfunc.pod
pp.c
t/op/splice.t [new file with mode: 0644]

index 6678322..0034da7 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -902,6 +902,7 @@ t/op/repeat.t               See if x operator works
 t/op/runlevel.t                See if die() works from perl_call_*()
 t/op/sleep.t           See if sleep works
 t/op/sort.t            See if sort works
+t/op/splice.t           See if splice works
 t/op/split.t           See if split works
 t/op/sprintf.t         See if sprintf works
 t/op/stat.t            See if stat works
index 909fa80..089bd48 100644 (file)
@@ -3336,11 +3336,13 @@ Removes the elements designated by OFFSET and LENGTH from an array, and
 replaces them with the elements of LIST, if any.  In list context,
 returns the elements removed from the array.  In scalar context,
 returns the last element removed, or C<undef> if no elements are
-removed.  The array grows or shrinks as necessary.  If LENGTH is
-omitted, removes everything from OFFSET onward.  The following
-equivalences hold (assuming C<$[ == 0>):
+removed.  The array grows or shrinks as necessary.
+If OFFSET is negative then it start that far from the end of the array.
+If LENGTH is omitted, removes everything from OFFSET onward.
+If LENGTH is negative, leave that many elements off the end of the array.
+The following equivalences hold (assuming C<$[ == 0>):
 
-    push(@a,$x,$y)     splice(@a,$#a+1,0,$x,$y)
+    push(@a,$x,$y)     splice(@a,@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)
diff --git a/pp.c b/pp.c
index a0949a1..6cc98fd 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -2589,8 +2589,11 @@ PP(pp_splice)
            DIE(no_aelem, i);
        if (++MARK < SP) {
            length = SvIVx(*MARK++);
-           if (length < 0)
-               length = 0;
+           if (length < 0) {
+               length += AvFILLp(ary) - offset + 1;
+               if (length < 0)
+                   length = 0;
+           }
        }
        else
            length = AvMAX(ary) + 1;            /* close enough to infinity */
diff --git a/t/op/splice.t b/t/op/splice.t
new file mode 100644 (file)
index 0000000..06e3509
--- /dev/null
@@ -0,0 +1,34 @@
+#!./perl
+
+print "1..9\n";
+
+@a = (1..10);
+
+sub j { join(":",@_) }
+
+print "not " unless j(splice(@a,@a,0,11,12)) eq "" && j(@a) eq j(1..12);
+print "ok 1\n";
+
+print "not " unless j(splice(@a,-1)) eq "12" && j(@a) eq j(1..11);
+print "ok 2\n";
+
+print "not " unless j(splice(@a,0,1)) eq "1" && j(@a) eq j(2..11);
+print "ok 3\n";
+
+print "not " unless j(splice(@a,0,0,0,1)) eq "" && j(@a) eq j(0..11);
+print "ok 4\n";
+
+print "not " unless j(splice(@a,5,1,5)) eq "5" && j(@a) eq j(0..11);
+print "ok 5\n";
+
+print "not " unless j(splice(@a, 20, 0, 12, 13)) eq "" && j(@a) eq j(0..13);
+print "ok 6\n";
+
+print "not " unless j(splice(@a, -@a, @a, 1, 2, 3)) eq j(0..13) && j(@a) eq j(1..3);
+print "ok 7\n";
+
+print "not " unless j(splice(@a, 1, -1, 7, 7)) eq "2" && j(@a) eq j(1,7,7,3);
+print "ok 8\n";
+
+print "not " unless j(splice(@a,-3,-2,2)) eq j(7) && j(@a) eq j(1,2,7,3);
+print "ok 9\n";