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

PerlHash.get_pmc_keyed of non existing key

0 views
Skip to first unread message

Gordon Henriksen

unread,
Aug 22, 2003, 11:06:25 PM8/22/03
to perl6-l...@perl.org
Taking a thread from Perl 6 Internals. Will Perl 6 support this behavior?

$ perl <<'EOT'
my @ary;
my $ref = \$ary[0];
$$ref = "value";
print '$ary[0] : ', $ary[0], "\n";
EOT
$ary[0] : value

Presumably the Perl 6 would be:

my @ary;
my $ref = \@ary[0];
$$ref = "value";
print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value

If that's supported, then how will this behave?

my @cows of Cow;
my $slot = \@cows[0];
$$slot = new Dog;

Do we wind up with Clarus or an exception? (Never mind whether you take
exception with Clarus.) Hopefully an exception, from a user's POV. And
this?

my @cows of Cow:
my @cats of Cat;
my $ref = \@cows[0];
@cats[0] := $$ref;
@cats[1] := @cows[0]; # Just to hammer the point home....
$$ref = new Dog;

But then there's a question for p6i as to how all the above happens.

Gordon Henriksen
mali...@mac.com

Luke Palmer

unread,
Aug 23, 2003, 10:37:50 AM8/23/03
to Gordon Henriksen, perl6-l...@perl.org
Gordon Henriksen writes:
> Taking a thread from Perl 6 Internals. Will Perl 6 support this behavior?
>
> $ perl <<'EOT'
> my @ary;
> my $ref = \$ary[0];
> $$ref = "value";
> print '$ary[0] : ', $ary[0], "\n";
> EOT
> $ary[0] : value
>
> Presumably the Perl 6 would be:
>
> my @ary;
> my $ref = \@ary[0];
> $$ref = "value";
> print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value

That has to do with autovivification semantics. Particularly, do things
autovivify when you take a nonconstant reference to them. I think they
should, and that wasn't one of those cases where autovivi was broken, so
it probably will.

> If that's supported, then how will this behave?
>
> my @cows of Cow;
> my $slot = \@cows[0];
> $$slot = new Dog;
>
> Do we wind up with Clarus or an exception? (Never mind whether you take
> exception with Clarus.) Hopefully an exception, from a user's POV.

Definitely.

> And this?
>
> my @cows of Cow:
> my @cats of Cat;
> my $ref = \@cows[0];
> @cats[0] := $$ref;
> @cats[1] := @cows[0]; # Just to hammer the point home....
> $$ref = new Dog;

I would assume that's also an error. @cats C<returns Cat> [1], and if
you bind part of it to something that returns a non-cat, there should be
an exception... or a compile error.

Luke

Gordon Henriksen

unread,
Aug 23, 2003, 12:13:05 PM8/23/03
to perl6-l...@perl.org

On Saturday, August 23, 2003, at 10:37 , Luke Palmer wrote:

> Gordon Henriksen writes:
>> Taking a thread from Perl 6 Internals. Will Perl 6 support this
>> behavior?
>>
>> $ perl <<'EOT'
>> my @ary;
>> my $ref = \$ary[0];
>> $$ref = "value";
>> print '$ary[0] : ', $ary[0], "\n";
>> EOT
>> $ary[0] : value
>>
>> Presumably the Perl 6 would be:
>>
>> my @ary;
>> my $ref = \@ary[0];
>> $$ref = "value";
>> print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value
>
> That has to do with autovivification semantics. Particularly, do
> things autovivify when you take a nonconstant reference to them. I
> think they should, and that wasn't one of those cases where autovivi
> was broken, so it probably will.

Exactly what I was arguing on p6i—autovivify in lvalue context, but not
in rvalue context. i.e., both of these programs should work as specified
in comments:

my @ary;
my $ref = \@ary[0];
$$ref = "value";
print '@ary[0] : ', @ary[0], "\n";

# @ary[0] : value

my %hash = { a => 1, b => 2 };
my $temp = %hash{c};
print exists %hash{c}? "exists\n" : "DNE\n";
# DNE

>> And this?
>>
>> my @cows of Cow:
>> my @cats of Cat;
>> my $ref = \@cows[0];
>> @cats[0] := $$ref;
>> @cats[1] := @cows[0]; # Just to hammer the point home....
>> $$ref = new Dog;
>
> I would assume that's also an error. @cats C<returns Cat> [1], and if
> you bind part of it to something that returns a non-cat, there should
> be an exception... or a compile error.

This particular example would be catchable at compile-time, ideally—it
would require type inference, but it's catchable at compile time. But in
the general case? Where the array, or the reference, or both are untyped
and passed in from someplace else, their types/constraints not knowable
until runtime? Where would the exception throw?

Throw here, at bind time?

@cats[0] := $$ref;

The undef value would need to know about its container (or, more
appropriately:) said container's constraints. But undef is still
compatible with both containers. To expand on that, what about this case?

my @listA is any (Cow | Cat);
my @listB is any (Cat | Dog);
@listA[0] := @listB[0];

Author could expect a Cat to be compatible and for the code to run. But
very action-at-a-distance-ey if it did work.

Or throw here, at assign time?

$$ref = new Dog;

The undef PMC would need to know about all of its containers and all of
their constraints. Yuck! With weak references, too, because @cows could
be GC'd while @cats remained valid.

Gordon Henriksen
mali...@mac.com

Gordon Henriksen

unread,
Aug 23, 2003, 12:26:10 PM8/23/03
to Sean O'Rourke, Luke Palmer, perl6-l...@perl.org
On Saturday, August 23, 2003, at 11:14 , Sean O'Rourke wrote:

> Luke Palmer <fibo...@babylonia.flatirons.org> writes:


>
>> Gordon Henriksen writes:
>>> my $ref = \@ary[0];
>>> $$ref = "value";
>>> print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value
>>
>> That has to do with autovivification semantics. Particularly, do
>> things
>> autovivify when you take a nonconstant reference to them.
>

> I think it's better seen as part of the semantics of references to
> nonexistent values. When you take a ref to a value slot that doesn't
> exist, you effectively create a tied variable that knows how to
> create that slot, and will do so only when you assign to it.

Really? I'd think that it would create the slot immediately. Perl 5 does.

perl <<'EOT'
my %hash;
my $ref = \$hash{key};
print exists $hash{key}? "exists\n" : "DNE\n";
EOT
exists

Also means that this...

my $ref = \%hash{blah}{blort}[123]{moogle};

is just a chain of autovivifying subscript operations, rather than the
construction of some horribly complex object that knows how to create
all of those intermediate aggregates. Also means that this

%hash{blah}{blort}[123]{moogle} = 1;

work's just the same way as the reference creation (up until it assigns
a value instead of creating a reference object).


OTOH, this in Perl 5

my $val = $hash{blah}{blort}[123]{moogle};

Was always annoyingly non-orthogonal to simpler constructs, in that it
vivified all but the last container. But that's separately solvable.

Gordon Henriksen
mali...@mac.com

Benjamin Goldberg

unread,
Aug 23, 2003, 9:40:24 PM8/23/03
to perl6-l...@perl.org

Gordon Henriksen wrote:
>
> Taking a thread from Perl 6 Internals. Will Perl 6 support this behavior?
>
> $ perl <<'EOT'
> my @ary;
> my $ref = \$ary[0];
> $$ref = "value";
> print '$ary[0] : ', $ary[0], "\n";
> EOT
> $ary[0] : value
>
> Presumably the Perl 6 would be:
>
> my @ary;
> my $ref = \@ary[0];
> $$ref = "value";
> print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value
>
> If that's supported, then how will this behave?
>
> my @cows of Cow;
> my $slot = \@cows[0];
> $$slot = new Dog;

Well, Perl6 can infer (at compile time) that $slot is a reference to a
Cow, and from that, it can infer that $$slot may only contain a Cow.
Thus, it should be catchable at compile time.

OTOH, the following is not catchable at compile time:

my @cows of Cow;
my @dogs of Dog;
my $ref = int(rand(2)) ? \@cows[0] : \@dogs[0];
$$ref = new Dog;

All that Perl6 can infer at compile time about $ref is that it is a
reference to any(Cow, Dog). So, the assignment is legal at compile
time.

Thus, *some* sort of runtime check needs to be made.

I suppose that instead of $ref being a PerlRef (or however we manage
references), it would be a PerlTypeConstrainedRef, which throws an
exception if you try to store a value the wrong type into it.

> Do we wind up with Clarus or an exception? (Never mind whether you take
> exception with Clarus.)

Clarus would be if we had an object whose type was all(Cow, Dog), eh?:)

> Hopefully an exception, from a user's POV.

An exception at compile time the code you presented, an exception at run
time for the code I presented.

> And this?
>
> my @cows of Cow:
> my @cats of Cat;
> my $ref = \@cows[0];

Ok.

> @cats[0] := $$ref;

Ok, although this is mostly a no-op.

> @cats[1] := @cows[0]; # Just to hammer the point home....

A compile time error.

> $$ref = new Dog;

A compile time error due to type inferencing.
(If type inferencing were insufficient, it would be a run-time error).

> But then there's a question for p6i as to how all the above happens.

I suppose that a PerlRef would be a PMC which has another PMC stored in
it's ->cache.struct_value component; storing and fetching it's contents
would be done via VTABLE_set_pmc and VTABLE_get_pmc.

I suppose that a PerlTypeConstrainedRef would, in addition, have a
PerlClass PMC in it's PMC_data, and check for the appropriate isa
relationship before allowing new data to be stored into it.

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

0 new messages