Kaiepi
Kaiepi

Reputation: 3230

How are enums augmentable?

In Raku, HOWs must expose a list of archetypes through an archetypes method, which is used to determine what broader features of types a type implements, e.g. parametricity or composability. I noticed Metamodel::EnumHOW (the HOW used with enums) has the augmentable archetype, which is given to types that can be extended after composition with the augment keyword when the MONKEY-TYPING pragma is enabled.

My first guess at why enums would be augmentable would be to allow enum values to be added, so I tried writing this:

use v6;
use MONKEY-TYPING;

enum Foo <foo bar baz>;
augment enum Foo <qux>;
say qux;

But this throws:

bastille% raku test.raku
===SORRY!=== Error while compiling /home/morfent/test.raku
Redeclaration of symbol 'Foo'.
at /home/morfent/test.raku:5
------> augment enum Foo⏏ <qux>;

So they're probably not intended to be augmented in this way.

My next guess was that they're intended to be augmentable with regards to the enum values, not the enum type itself. augment, interestingly, doesn't take into account what HOW a type actually has when you tell it what kind of type you're augmenting, so I tried augmenting an enum like you would a class:

use v6;
use MONKEY-TYPING;

enum Foo <foo bar baz>;

augment class Foo {
    proto method is-foo(::?CLASS:D: --> Bool:D) {*}
    multi method is-foo(foo: --> True)          { }
    multi method is-foo(::?CLASS:D: --> False)  { }
}

say foo.is-foo;

Which works:

bastille% raku test.raku
True

But this doesn't feel like how you're intended to augment enums to me. This usage of augment is rather weird, and there isn't any implication that this should be possible to do from its documentation. How are you intended to augment enums?

FAQ

is-foo is rather heavy-handed with how it uses features of signatures and parameters. It depends on the following:

Since foo is a more specific type than ::?CLASS:D (an alias for Foo:D), when invoking this method on foo, the foo multi will be selected and True will get returned, but in any other case, the ::?CLASS:D multi will be selected and False will be returned.

Upvotes: 8

Views: 168

Answers (1)

bobthecimmerian
bobthecimmerian

Reputation: 91

In Java you can add almost arbitrary attributes and functions to enums. So I do think augment in the way you describe could make sense. For example:

use MONKEY-TYPING;

enum Days(Monday => 1, Tuesday => 2, Wednesday => 3, Thursday => 4, Friday => 5, Saturday => 6, Sunday => 7); 

augment class Days {
    proto method is-weekend(::?CLASS:D: --> Bool:D) {*} 
    multi method is-weekend(Saturday: --> True)          { } 
    multi method is-weekend(Sunday: --> True) {}
    multi method is-weekend(::?CLASS:D: --> False)  { } 

    proto method days-til-weekend(::?CLASS:D: --> Int:D) {*}
    # there is probably a better way to express this, but
    # hopefully the concept is clear
    multi method days-til-weekend(Monday: --> 4) {}
    ...
}

say Monday.is-weekend;
say Wednesday.days-til-weekend;
say Saturday.is-weekend;

Upvotes: 6

Related Questions