Array theory

djberg96 on 2004-05-12T23:26:55

Like, oh....my...gawd! An entry about Perl!

This is probably an old topic, but I'm just hitting it for the first time, so leave me alone.

In Perl (and most scripting languages) you can do this: my @array = ();

$array[2] = "foo";

foreach my $e(@array){ print "Element: [$e]\n"; }
Index 2 is out of range, but Perl DWIM and sets index 2 to "foo", and indices 0 and 1 to undef. Ok, no problem. But I get an error if I try this: my @array = (); $array[-1] = "foo"; What would I expect? I would expect it to simply slap a "foo" as the last (and only) element. The next question you're about to ask me (I can read your mind) is, "ok, what about something like $array[-3] = 'foo';"?

In that case, I would expect it to act like a positive integer, only in reverse. Thus, $array[-3] would result in an array ("foo",undef,undef).

It appears that every language designer on the planet disagrees with me. But....why? It feels like language designers chose to be flexible on positive indices, but resorted back to C for negative indices.

Not that I'm crying or anything - just curious.


arrays with negative indices

rjbs on 2004-05-13T00:43:24

I'm not sure what you're complaint is, exactly. I think negative indices are pretty useful, but you seemed to only test them on empty arrays. They're useful on longer arrays because -3 means "start at the right and go back three; if you get to the left, give up." So, given @foo = (1, 2, 3), $foo[-3] is 1, $foo[-2] is 2, and $foo[-10] is undef.

I would've thought that C would do something horrid like (type)*(array - index), but my C is lousy.

Re:arrays with negative indices

djberg96 on 2004-05-13T01:24:23

I'm not complaining about negative arrays. I'm complaining that the behavior of arrays is inconsistent with regards to empty arrays and negative indices, specifically.

Re:arrays with negative indices

rjbs on 2004-05-13T01:34:17

How is it inconsistent? Given @foo=(1,2,3); $foo[-10] does not exist. If fetched, it returns the "does not exist" value, which is undef. It's also C. It's not a valid lvalue, so it should throw an error.

After all the -1 subscript is "first existing element from the right" not "a new element at the end." Or am I being thick?

Re:arrays with negative indices

djberg96 on 2004-05-13T01:50:51

You're talking about reference. I'm talking about assignment, e.g.

@foo = ();
$foo[10] = "foo"; # legal
$foo[-10] = "foo"; # illegal

In the former case, index 10 does not exist. I create it and indices 0 to 9 now exist as undef. In the latter case, index -10 does not exist, but I cannot assign to it. Why not allow me to assign to a negative index on an empty array?

Re:arrays with negative indices

jsmith on 2004-05-13T05:52:07

$foo[10] = "foo" is the same as (assuming an empty @foo), @foo = ( (undef) x 9, "foo", (undef) x 0)

You want $foo[-10] = "foo" to be the same as @foo = ( (undef) x $m, "foo", (undef) x $n ), but what are $m and $n ? (On reflection, $m should probably be zero and $n be 9? What's the benefit of this behavior?)

Does $foo[-10] = $bar[-5] = "foo" result in @foo being a different size than @bar ? (Based on our reflection above, they would be different sizes.)

If @foo is already defined, then what happens when we use a negative index that takes us off the left? (We are already allowed to use a positive index that takes us off the right--this maintains the symmetry we are seeking.) Do we pad the right with undefs? Or do we shift everything to the right by padding the left with undefs? How do we break the symmetry between the two selections (padding the right vs. padding the left/shifting to the right)? Both can be consistent with our desired behavior for previously empty arrays.

For what it is worth

sky on 2004-05-13T08:12:36

I totally agree with you, I think that it is backwards that it doesn't DWIM. The other comments are just the typical lame gut reaction by people who don't get it comments.

Re:For what it is worth

vsergu on 2004-05-13T14:46:51

I don't think it's a gut reaction, lame or otherwise. The proponents seem to be the ones who haven't thought things through. It's not at all clear what DWIM behavior is in this case. It has to handle nonempty arrays as well:

my @foo = 1 .. 3;
$foo[10] = "foo"; # legal
$foo[-10] = "foo"; # illegal, but what do you expect?

Re:For what it is worth

sky on 2004-05-13T14:53:41

In fine tradition with language design flames I am going to point out that dbjerg points out exactly what he expects and I get this, you however do not.

Therefore I don't see any reason to tell you what I expect, because I expect what dbjerg already said and you didn't get that.

Re:For what it is worth

vsergu on 2004-05-13T15:14:12

I'm sorry, but I see nothing in djberg96's posts that addresses nonempty arrays at all. Both rjbs and jsmith have raised the issue, but neither has received an answer.

Re:For what it is worth

sky on 2004-05-13T15:18:14

See, I get what he means, you don't.

djberg96> In that case, I would expect it to act like a positive
djberg96> integer, only in reverse. Thus, $array[-3] would result
djberg96> in an array ("foo",undef,undef).

Easy eh?

Re:For what it is worth

vsergu on 2004-05-13T15:29:06

I assumed he was talking about starting with an empty array there. I'm talking about when the array already has something in it. Do you really mean to say that after this

my @foo = 1 .. 3;
$foo[-4] = 'foo';

you would expect to lose what had been in the array before and be left with just ('foo', undef, undef, undef)?

Re:For what it is worth

sky on 2004-05-13T15:32:03

I give up. You just don't get it.

Re:For what it is worth

djberg96 on 2004-05-13T15:28:19

my @foo = 1 .. 3;
$foo[10] = "foo"; # legal
$foo[-10] = "foo"; # illegal, but what do you expect?
For brevity's sake, let's cut the index down to 5. So, using your example, $foo[5] = "foo" would be:
(1,2,3,undef,undef,"foo").
So, what would I expect from $foo[-5] = "foo"? I would expect @foo to be:
# One less undef, because the reverse index starts at -1, not -0.
("foo",undef,1,2,3).

Re:For what it is worth

vsergu on 2004-05-13T15:50:15

Thanks. So you expect it to move the existing array elements into other places. Is there anyone else out there besides you and sky who would expect that?

I think the reason that assigning to nonexistent array elements with negative indices doesn't work is that there's no consistent way to do it.

I can only guess that it seems consistent to you because, from the point of view of someone who only uses negative array indices, the equivalent assignment with a positive index is "moving" array elements. But I don't think many people look at negative indices as being just as "real" as positive indices. Negative indices are shortcuts; positive indices are the actual positions.

Maybe I'm wrong, and more people do see things your way, but if so they do seem to be underrepresented among language designers.

Re:For what it is worth

phillup on 2004-05-13T19:09:51

Is there anyone else out there besides you and sky who would expect that?


Not normally, but in Perl? Yes, I would.

Here is why...

Suppose you have an array, of any size. When you hit it with an assignment using an index who's absolute value is larger than the array size... it will, basically perform a "push" onto the end of the array (the right side) until the array size = the absolute value of the index if the index is positive.

Then it will do the assignment.

So, it is a two step process for positive index values... grow the array to the needed size... then make the assignment.

With this in mind, I would expect Perl to grow the array from the other direction (like an "unshift") for index values that are negative.

The sign of the index value would determine which end grows, the absolute value would determine the amount of growth. (This is for situations where the absolute value of the index is larger than the size of the array.)

I would consider that to be "consistent". The fact that it doesn't do this, however... is not surprising. Because I'm not aware of any other language that does it...

But, I do think that would be the "right thing" and the "do what I mean thing" for the situation.