【问题标题】:How are enums augmentable?枚举如何增强?
【发布时间】:2020-09-17 16:18:18
【问题描述】:

在 Raku 中,HOW 必须通过 archetypes 方法公开一个原型列表,该方法用于确定类型实现的类型的更广泛的特性,例如参数性或可组合性。我注意到Metamodel::EnumHOW(与枚举一起使用的方式)具有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,有趣的是,当你告诉它你正在扩充哪种类型时,它没有考虑到一个类型实际上有什么,所以我尝试像你对一个类一样扩充一个枚举:

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 在使用签名和参数的特性方面相当严厉。这取决于以下几点:

  • 常量值可以像签名中的类型一样使用。这包括在编译时处理的枚举值。
  • 可以使例程始终返回一个常量值,方法是为其签名的返回值类型设置一个。
  • 签名中任何给定参数的变量都是可选的。
  • 当像这样在第一个参数之后放置一个冒号时,第一个参数就是签名的invocant。对于方法,这允许您随意输入self。
  • ::?CLASS 是在其范围内声明方法的类的别名。它存在于类和角色主体中,因此尽管 Foo 不是真正的类,但这就是该符号所指的。
  • :D 是一个类型笑脸,表示一个类型应该只对它自己的实例进行类型检查,而不是类型检查类似它的类型对象。

由于foo 是比::?CLASS:D(Foo:D 的别名)更具体的类型,因此在foo 上调用此方法时,将选择foo multi 并返回True,但在任何其他情况下,::?CLASS:D multi 将被选中,False 将被返回。

【问题讨论】:

    标签: enums metaprogramming raku


    【解决方案1】:

    在 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;
    

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 2012-09-16
      • 2020-08-21
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      • 2021-12-21
      • 2010-09-11
      相关资源
      最近更新 更多