Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Array Holes

9 views
Skip to first unread message

Luke Palmer

unread,
Jan 13, 2006, 5:33:23 PM1/13/06
to perl6language
In perl 5:

my @a = (1,2,3);
delete $a[1];
print exists $a[1];

This is false, whereas $a[0] and $a[2] do exist. This is creepy. Not
only is it creepy, it raises a whole bunch of questions with
nontrivial answers:

* does *@a include nonexistent elements?
* does map iterate over nonexistent elements?
* how do you store nonexistence for native packed arrays

And, what I always say, if the proper abstractions are being used,
then all decisions become obvious truths. Since the answers to these
are not obvious truths, proper abstractions must not be in use.

Anyway, I want this behavior to die. Maybe we should get rid of
.delete() on arrays, or maybe we should equate it with
.splice($idx,1).

Luke

Nicholas Clark

unread,
Jan 13, 2006, 6:21:49 PM1/13/06
to Luke Palmer, perl6language

I'm not sure if it came in as a side effect of pseudohashes. Sadly I no
longer have access to the AIX box where I built perl 5.000, so I can't
check what really old perl 5 makes of it. I have this hunch that
using exists on an array element is not legal syntax.

I have this vague memory that there's an even weirder piece of emergent
behaviour with arrays and exists, but I can't remember what it is. Possibly
something to do with extending arrays, but checking the source for av_exists
I can't work out any way to make it do even stranger things. Maybe it was
just this:

#!perl -w

use strict;

sub check {
my $array = shift;
printf "%d:", scalar @$array;
foreach (0..9) {
print exists $array->[$_] ? " Y" : " n";
}
print "\n";
}

my @a;
check \@a;

my @b = @a;
check \@b;

$#a=5;
check \@a;

@b = @a;
check \@b;

__END__
0: n n n n n n n n n n
0: n n n n n n n n n n
6: n n n n n n n n n n
6: Y Y Y Y Y Y n n n n


Some undefs are more equal than others.

Nicholas Clark

Larry Wall

unread,
Jan 13, 2006, 6:48:48 PM1/13/06
to perl6language
On Fri, Jan 13, 2006 at 10:33:23PM +0000, Luke Palmer wrote:
: In perl 5:

:
: my @a = (1,2,3);
: delete $a[1];
: print exists $a[1];
:
: This is false, whereas $a[0] and $a[2] do exist. This is creepy. Not
: only is it creepy, it raises a whole bunch of questions with
: nontrivial answers:
:
: * does *@a include nonexistent elements?
: * does map iterate over nonexistent elements?

The answer in Perl 5 is "yes", but Perl 6 doesn't have to have the same
default. In many ways you'd want a sparse array to behave more like a hash.
But then how often do you ask a hash only for its values?

Whatever the answer, it probably has to apply to

my @a;
@a[0] = '1';
@a[2] = '3';
print exists $a[1];

as well as the explicit delete case. Are we going to pitch an exception
for writing beyond the end of an array? That seems a bit anti-Perlish.

: * how do you store nonexistence for native packed arrays

Well, packed arrays aren't the default, but obviously if you want to
support sparseness in packed arrays you'd have to do something like
one of:

1) Distinguish a value that doesn't "exist" (NaN, for instance).
2) Record the existence out-of-band, say, in a bitmap.
3) Only store "runs" of existing packed data.

Approach #2 has the advantage that you can track definedness along
with existence for native types that don't contain the Maybe concept.
However, I think our default stance was that the user probably uses
native types because they want things to run fast, so it's okay to
pitch an exception if you ask a native type to remember something
it's incapable of remembering. But "smart" native types are still
a possibility.

: And, what I always say, if the proper abstractions are being used,


: then all decisions become obvious truths. Since the answers to these
: are not obvious truths, proper abstractions must not be in use.

Yeah, well... Abstractions are complete hypocrites--they make other
things obvious while refusing to be obvious themselves.

: Anyway, I want this behavior to die. Maybe we should get rid of


: .delete() on arrays, or maybe we should equate it with
: .splice($idx,1).

Or maybe we support sparse arrays as one container type.

I actually used a crowbar last week. It wasn't pretty, but it got
the job done. Well, okay, it got the job started...I still have a
hole in my living room wall, but my chief interest at the time was
to make sure my house wasn't going to burn down. That's about as
much abstraction as you could wish for in real life.

Larry

Austin Hastings

unread,
Jan 14, 2006, 4:23:36 PM1/14/06
to Larry Wall, perl6language
Larry Wall wrote:

>Whatever the answer, it probably has to apply to
>
> my @a;
> @a[0] = '1';
> @a[2] = '3';
> print exists $a[1];
>
>as well as the explicit delete case. Are we going to pitch an exception for writing beyond the end of an array? That seems a bit anti-Perlish.
>
>

What's the semantic difference between "exists but is undefined" and
"does not exist"?

IOW:

my @a = (1,2,3);

@a[1] = undef;

print exists @a[1];
print @a[1];

versus:

my @a = (1,2,3);

delete @a[1];

print exists @a[1];
print @a[1];

If I try to store @a[1], it auto(re)vivifies, right?

If I fetch @a[1], do I get an exception or just an undef?

To force undef, do I use "err" or "//"?

my $a1 = @a[1] err undef;
my $a1 = @a[1] // undef;

Does @a.k return different results? (0..2) vs (0,2)

>: * how do you store nonexistence for native packed arrays
>
>
>

We've beaten this horse, or one that looks vanishingly like it, a bunch
of times.

1. Implementation issue. Throw it to p6i.
2. For infrequent exceptions, create an exception-list.
3. For frequent exceptions, create a bitmap.
4. For exceptions in unbalanced data, create an escape value.

>: Anyway, I want this behavior to die. Maybe we should get rid of
>: .delete() on arrays, or maybe we should equate it with
>: .splice($idx,1).
>
>Or maybe we support sparse arrays as one container type.
>
>

Sure, but what's the default behavior?

If I consume the endpoints of an array, using shift or pop, how is that
different from consuming the middle?

my @a = (1,2,3);
shift @a;
shift @a;

print @a.indexof(3); # 0 or 2?

Based on that, I'll argue that the default array mode is "contains a
list," which means that array contents should act like lists. Delete
something in the middle, and you have a shorter list, not a list with a
hole in it.

Harrays and Arrashes can be different types, or maybe can just be
properties of the basic sigillated types.

my @a = (1,2,3) is arrash; # sparse

my %h = (1 => 'a', 2 => 'b') is harray;

>I actually used a crowbar last week. It wasn't pretty, but it got
>the job done. Well, okay, it got the job started...I still have a
>hole in my living room wall, but my chief interest at the time was
>to make sure my house wasn't going to burn down. That's about as
>much abstraction as you could wish for in real life.
>
>

Dude, you're scaring me. Should there be a license required for home
ownership?

=Austin

0 new messages