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?
Foo.is-foo
doesn't appear to have any code? What is it doing?is-foo
is rather heavy-handed with how it uses features of signatures and parameters. It depends on the following:
self
however you want.::?CLASS
is an alias for the class whose scope a method is declared in. This exists in class and role bodies, so despite Foo
not really being a class, that is what the symbol is referring to.:D
is a type smiley denoting that a type should only typecheck against its own instances, not type objects that typecheck like it.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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With