枚举如何扩充?
How are enums augmentable?
在 Raku 中,HOW 必须通过 archetypes
方法公开 archetypes 的列表,该方法用于确定类型实现的更广泛的特征,例如参数化或可组合性。我注意到 Metamodel::EnumHOW
(与枚举一起使用的 HOW)具有 augmentable
原型,当 MONKEY-TYPING
pragma 时,它被赋予可以在使用 augment
关键字组合后扩展的类型已启用。
我对为什么枚举可以扩充的第一个猜测是允许添加枚举值,所以我试着写这个:
use v6;
use MONKEY-TYPING;
enum Foo <foo bar baz>;
augment enum Foo <qux>;
say qux;
但这抛出:
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>;
所以它们可能不打算以这种方式增强。
我的下一个猜测是,它们旨在针对枚举值进行扩充,而不是枚举类型本身。 augment
,有趣的是,当你告诉它你正在扩充哪种类型时,它并没有考虑到一个类型实际上有什么,所以我尝试像扩充一个枚举一样 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;
哪个有效:
bastille% raku test.raku
True
但这并不像你打算给我增加枚举的方式。 augment
的这种用法相当奇怪,并且没有任何暗示应该可以从其文档中做到这一点。您打算如何扩充枚举?
常见问题
Foo.is-foo
好像没有任何代码?它在做什么?
is-foo
在使用签名和参数的特性方面相当笨拙。这取决于以下内容:
- 常量值可以像签名中的类型一样使用。这包括在编译时处理的枚举值。
- 通过将其签名的 return 值类型设为一个例程,可以使例程始终 return 为常量值。
- 签名中任何给定参数的变量都是可选的。
- 像这样在第一个参数之后放置一个冒号时,第一个参数就是签名的 invocant。对于方法,这允许您根据需要键入
self
。
::?CLASS
是 class 的别名,其作用域中声明了一个方法。它存在于 class 和角色主体中,因此尽管 Foo
并不是真正的a class,这就是符号所指的。
:D
是一个类型笑脸,表示一个类型应该只针对它自己的实例进行类型检查,而不是像它一样进行类型检查的类型对象。
由于 foo
是比 ::?CLASS:D
(Foo:D
的别名)更具体的类型,因此在 foo
上调用此方法时,foo
multi 将被选中并且 True
将被 returned,但在任何其他情况下,::?CLASS:D
multi 将被选中并且 False
将被 returned。
在 Java 中,您几乎可以向枚举添加任意属性和函数。所以我确实认为以你描述的方式进行扩充是有道理的。例如:
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;
在 Raku 中,HOW 必须通过 archetypes
方法公开 archetypes 的列表,该方法用于确定类型实现的更广泛的特征,例如参数化或可组合性。我注意到 Metamodel::EnumHOW
(与枚举一起使用的 HOW)具有 augmentable
原型,当 MONKEY-TYPING
pragma 时,它被赋予可以在使用 augment
关键字组合后扩展的类型已启用。
我对为什么枚举可以扩充的第一个猜测是允许添加枚举值,所以我试着写这个:
use v6;
use MONKEY-TYPING;
enum Foo <foo bar baz>;
augment enum Foo <qux>;
say qux;
但这抛出:
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>;
所以它们可能不打算以这种方式增强。
我的下一个猜测是,它们旨在针对枚举值进行扩充,而不是枚举类型本身。 augment
,有趣的是,当你告诉它你正在扩充哪种类型时,它并没有考虑到一个类型实际上有什么,所以我尝试像扩充一个枚举一样 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;
哪个有效:
bastille% raku test.raku
True
但这并不像你打算给我增加枚举的方式。 augment
的这种用法相当奇怪,并且没有任何暗示应该可以从其文档中做到这一点。您打算如何扩充枚举?
常见问题
Foo.is-foo
好像没有任何代码?它在做什么?
is-foo
在使用签名和参数的特性方面相当笨拙。这取决于以下内容:
- 常量值可以像签名中的类型一样使用。这包括在编译时处理的枚举值。
- 通过将其签名的 return 值类型设为一个例程,可以使例程始终 return 为常量值。
- 签名中任何给定参数的变量都是可选的。
- 像这样在第一个参数之后放置一个冒号时,第一个参数就是签名的 invocant。对于方法,这允许您根据需要键入
self
。 ::?CLASS
是 class 的别名,其作用域中声明了一个方法。它存在于 class 和角色主体中,因此尽管Foo
并不是真正的a class,这就是符号所指的。:D
是一个类型笑脸,表示一个类型应该只针对它自己的实例进行类型检查,而不是像它一样进行类型检查的类型对象。
由于 foo
是比 ::?CLASS:D
(Foo:D
的别名)更具体的类型,因此在 foo
上调用此方法时,foo
multi 将被选中并且 True
将被 returned,但在任何其他情况下,::?CLASS:D
multi 将被选中并且 False
将被 returned。
在 Java 中,您几乎可以向枚举添加任意属性和函数。所以我确实认为以你描述的方式进行扩充是有道理的。例如:
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;