Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent core perl behaviour ? #898

Closed
p5pRT opened this issue Nov 27, 1999 · 4 comments
Closed

Inconsistent core perl behaviour ? #898

p5pRT opened this issue Nov 27, 1999 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 27, 1999

Migrated from rt.perl.org#1832 (status was 'resolved')

Searchable as RT1832$

@p5pRT
Copy link
Author

p5pRT commented Nov 27, 1999

From rick.delaney@home.com

David Cassell wrote​:

geoff_gunner@​my-deja.com wrote​:

Perl grows arrays on demand​:
@​array=(); # a nice empty array
$array[4]='x'; # elements 0..3 are undef; 4 is
'x'

So scalar @​array would return 4, right? And an offset
of 8 is meaningless at this point...

It is no more meaningless than the offset of 4 was after the line

  @​array=();

So​: let's say that you now do​:
splice(@​array, 8, 0, 'a', 'b', 'c');
elements 8, 9 and 10 should now be a, b and c,
right ? Wrong - they're at 5,6 and 7. Even
though you explicitly asked for the data to go
here, perl hasn't created the extra elements.

So. You ask Perl to do something absurd, and it
does the most logical thing it can find. But you don't
like it. Still, I don't think that makes it a bug.

I agree that the behaviour is not a bug but it seems there is a tiny
error in the docs for splice.

=item splice ARRAY,OFFSET,LENGTH,LIST

=item splice ARRAY,OFFSET,LENGTH

=item splice ARRAY,OFFSET

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 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,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[$x] = $y splice(@​a,$x,1,$y)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

These are not equivalent if $x &gt; $#a + 1.

May I suggest changing

If OFFSET is negative then it start that far from the end of the array.

to

If OFFSET is negative then it starts that far from the end of the array.
If OFFSET is greater than the last index of the array then it starts
from the last index plus one.

Please note that I've also changed "start" to "starts" so even if you
don't like it, at least the typo could be fixed. :-)

--
Rick Delaney
rick.delaney@​home.com

@p5pRT
Copy link
Author

p5pRT commented Dec 11, 2000

From [Unknown Contact. See original ticket]

This bug is still true. According to the docs the following two should be
equivalent.

$a[$x] = $y splice(@​a,$x,1,$y)

However, they are not. This simple case shows​:

$x[5]=5;
print $#x;
print "\n";
print join("​:", @​x);

# prints
5
:​::​::5

splice(@​x,5,1,7);
print $#x;
print "\n";
print join("​:", @​x);

# prints
0
5

-spp

@p5pRT
Copy link
Author

p5pRT commented Dec 23, 2000

From @simoncozens

On Mon, Dec 11, 2000 at 03​:31​:37PM -0500, Stephen P. Potter wrote​:

splice(@​x,5,1,7);
print $#x;
print "\n";
print join("​:", @​x);

# prints
0
5

This is even tested for​:

print "not " unless j(splice(@​a, 20, 0, 12, 13)) eq "" && j(@​a) eq j(0..13);
print "ok 6\n";

So what's right? Is it the documentation or the tests? If it's the
documentation​:

Inline Patch
--- pp.c~	Sun Dec 24 01:39:33 2000
+++ pp.c	Sun Dec 24 01:53:26 2000
@@ -3708,8 +3708,9 @@
 	length = AvMAX(ary) + 1;
     }
     if (offset > AvFILLp(ary) + 1)
-	offset = AvFILLp(ary) + 1;
-    after = AvFILLp(ary) + 1 - (offset + length);
+	av_fill(ary, offset + length);
+    
+    after = av_len(ary) + 1 - (offset + length);
     if (after < 0) {				/* not that much array */
 	length += after;			/* offset+length now in array */
 	after = 0;

And rewrite your own tests...

@p5pRT
Copy link
Author

p5pRT commented Apr 26, 2003

@rgs - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant