Perl 6是否应该能够解释来自不同来源的相同角色的包含?

bri*_*foy 8 grammar role perl6

想象一下表示为角色的一系列复杂语法,尽管这个简单的例子足以显示冲突:

role Alpha {
    token alpha { :i <[A..Z]> }
    }

role Digit {
    token digit { <[0..9]> }
    }

role Either
    does Alpha
    does Digit {
    token either { <alpha> | <digit> }
    }

grammar Thingy
    does Either
    does Alpha
    {
    token TOP { <alpha> <either>* }
    }

my $match = Thingy.parse( '1a3' );
dd $match;
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为Perl 6没有解开关系,以确定冲突实际上是来自同一来源的相同内容:

方法'alpha'必须由Thingy类解析,因为它存在于多个角色中

但是,阅读S14,我看到:

角色可能不会从类继承,但可能由其他角色组成.然而,直到课堂构成时间才评估这种"裙带"组合物.这意味着如果两个角色带来了同一个朋友,那就没有冲突 - 就好像这个类本身就引入了裙带角色而各自的角色没有.无论其结合方式如何,角色都不会与自身发生冲突.

我读到这意味着角色尽可能晚地应用,因此该课程Thingy将能够解开Alpha包含在两个不同部分中的角色.我认为这可以像创建构成最终类的所有角色的列表,然后将该列表仅应用于最终类.这样,类似的东西Either只会混合它定义的东西,并依赖于后来的构图引入Alpha.

当我尝试为各种(IETF)RFC实现语法时,我碰到了这个问题.其中许多引用了其他RFC的语法,这使得Perl 6无法通过C3解析继承.所以,我认为角色会断开关系.显然它没有.

Sin*_*nür 3

是的,Perl 6 应该能够解决来自不同来源的相同角色的包含问题。

角色的简单定义是:

角色封装了可以在类之间共享的某些行为或状态。

或者

角色是离散行为集合的名称。

因此,假设我们有一个Floatable可以漂浮在水面上的对象的行为,以及一个Sailable可以航行的对象的行为。当然,可以航行的物体也可以漂浮。ASloop自然可漂浮且可航行。事实上,和角色都传达相同的 行为,这一事实并不冲突。FloatableFloatableSailable

在 Perl 中,这按预期工作(它Moose也适用于):

#!/usr/bin/env perl

use v5.24; # why not
use warnings;

package Floatable {
    use Moo::Role;
    sub float { say "float" }
}

package Sailable {
    use Moo::Role;
    with 'Floatable';
    sub sail { $_[0]->float; say "sail" };
}

package Sloop {
    use Moo;
    with qw( Floatable Sailable );
}

my $s = Sloop->new;

$s->sail;
Run Code Online (Sandbox Code Playgroud)

这种行为是直观上显而易见的。

在查看Perl6 角色文档时我注意到的一个问题是缺乏简单的一句话定义:

角色在某些方面与类相似,因为它们是属性和方法的集合。它们的不同之处在于角色也仅用于描述对象行为的一部分以及角色如何应用于类。或者换句话说,类用于管理对象,角色用于管理行为和代码重用。

...

角色应用与类继承有很大不同。当角色应用于类时,该角色的方法将被复制到该类中。如果多个角色应用于同一个类,冲突(例如同名的属性或非多方法)会导致编译时错误,可以通过在类中提供同名的方法来解决。

显然,当perl6遇到两个提供完全相同行为的角色时,它会认为这是一种我认为不合理的冲突。

请注意以下示例中的细微区别:

#!/usr/bin/env perl

use v5.24; # why not
use warnings;

package Floatable {
    use Moo::Role;
    sub float { say "float" }
}

package Sailable {
    use Moo::Role;
    sub float { say "floating bonds to finance journey "}
    sub sail { $_[0]->float; say "sail" };
}

package Sloop {
    use Moo;
    with qw( Floatable Sailable );
}

my $s = Sloop->new;

$s->sail;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,冲突是可以预料的,因为两个不同的角色想要声称提供相同的行为。