Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Even languages with heavy-weight MOPs do not offer a programming interface to unapply/uncompose, the reverse of:

https://metacpan.org/dist/Moose/source/lib/Moose/Meta/Role/A...

https://github.com/rakudo/rakudo/blob/master/src/Perl6/Metam...

Reading the source codes, I think this is due to no one yet having requested the ability to do so. To me it feels like implementing this is possible, but tedious.

The simple work-around for the problem would be to rebless the instance. Example:

    class Structure {}
    role Floatable {}
    role Inhabitable {}
    class Houseboat extends Structure with Floatable with Inhabitable {}

    $hb = Houseboat new
    $s = Structure new
        $s apply Floatable, Inhabitable  # houseboat at run-time

    # stop swimming
    ### NYI
    ### $s unapply Floatable

    # make a new house that cannot swim
    $s1 = Structure new
        $s1 apply Inhabitable
        $s1 = $s rebless_into $s1


I guess in Raku you would create a Boat role, and you would create a clone of a House instance with the Boat role mixed in, when needed.

In Raku speak:

    my $house = House.new;
    my $houseboat = $house but Boat;
See: https://docs.raku.org/routine/but

There would be no need to de-compose.


But note that the point of an ECS is being able to dynamically change roles without recreating new entities. If changing a house into a houseboat means creating a new entity, then everyone who had a reference to the house would need to be informed of the new reference.


Doesn't de-composing have the same issue, though?


I'm not sure I follow. In ECSs that I'm familiar with, entities are integer IDs, not class objects. So adding or removing components (roles) to an entity doesn't make use of any language-level features, it's just calls to the ECS library. E.g. in JS:

    var id = ecs.createEntity()     // returns an int
    ecs.addComponent(id, 'house')
    ecs.addComponent(id, 'boat')

So, very different from the class-based approach being floated a few comments ago. Does that answer your question?


Liz suggested `but`, but that creates a new entity with the role mixed in.

Instead one can use `does` to mix in to an existing entity:

    role House {}
    role Boat {}

    my \id = 42;
    id does House;
    id does Boat;

    say id ~~ House; # True
(What's missing is the ability to drop a mixin once it's been added via `does`.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: