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
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:
- Constant values may be used like types in signatures. This includes enum values, which are dealt with at compile-time.
- A routine can be made to always return a constant value by making one its signature's return value's type.
- Variables for any given parameter in a signature are optional.
- When a colon is placed after the first parameter like this, that first parameter is the signature's invocant. In the case of methods, this allows you to type
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 despiteFoo
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.