Skip to content

Slot Semantics

Ovid edited this page Jun 9, 2020 · 7 revisions

Slot Semantics

After a bit of discussion on #cor, it turns out that having slot declarations being lexical and using the slot identifier name as the public name is causing some issues.

Slots are private (which works in isolation), but NEW constructor needs to be able to "see" the slots in all of the lexical scopes if they have :new or :new(optional) (unless NEW is implicitly in every class).

But what do we do for this?

class Parent {
    has $x :isa(Int) :new;
}

class Child isa Parent {
    has $x :isa(Str) :new;
}

In the above, we have a few issues.

First, if I call my $o = Child->new( x => 'bob'), what does the Child $x get? Internally, we have to build classes from the bottom to the top of the heirachy and the parent would get the child's type of the slot.

We also have similar issues with roles. There other issues, but that's a clear one that exposes all of the issues.

It seems like the problem here is that the variable holding the slot and the external name of the slot are tightly coupled.

The proposal to fix this is to decouple the name of the variable containing the slot and the attribute for the slot (similar to init_arg in Moo/se, but not quite the same).

I think this can be done with a new attribute called :name($identifier).

class Parent {
    # without a :name(...) attribute, the name is 'x'
    has $x :isa(Int) :new;
}

class Child isa Parent {
    has $x :isa(Str) :name(some_x) :new;
}

Now in the above, to construct it:

my $object = Child->new(
    x      => 42,
    some_x => 'DNA',
);

This means that for roles, we'd do the same thing. The slot variable would be lexically scoped, but the slot name would determine the name by which we read/write/construct the slot data.

A child could override the parent slot names, but role slot names would require the standard role exclusion and aliasing behaviors.

Clone this wiki locally