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

Should Perl 6 be able to untangle the inclusion of the same role from different sources?

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

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;

这是行不通的,因为 Perl 6 不会理清关系来弄清楚冲突实际上是来自同一来源的同一事物:

Method 'alpha' must be resolved by class Thingy because it exists in multiple roles

但是,阅读 S14,我明白了:

A role may not inherit from a class, but may be composed of other roles. However, this "crony" composition is not evaluated until class composition time. This means that if two roles bring in the same crony, there's no conflict--it's just as if the class pulled in the crony role itself and the respective roles didn't. A role may never conflict with itself regardless of its method of incorporation.

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

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

是的,Perl 6 应该能够理清包含来自不同来源的相同角色。

简单definitions of a role是:

A role encapsulates some piece of behavior or state that can be shared between classes.

A role is a name for a discrete collection of behaviors.

所以,假设我们有一个 Floatable 可以漂浮在水面上的物体的行为,以及一个 Sailable 可以航行的物体的行为。自然地,可以航行的物体可以漂浮。 A Sloop 自然是可以漂浮和航行的。 相同 Floatable 行为由 Floatable 和 [=13= 传达的事实没有冲突]角色。

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

这种行为是直观明显的行为。

我在查看 Perl6 documentation for roles 时注意到的一个问题是缺少简单的一句话定义:

Roles are in some ways similar to classes, in that they are a collection of attributes and methods. They differ in that roles are also meant for describing only parts of an object's behavior and in how roles are applied to classes. Or to phrase it differently, classes are meant for managing objects and roles are meant for managing behavior and code reuse.

...

Role application differs significantly from class inheritance. When a role is applied to a class, the methods of that role are copied into the class. If multiple roles are applied to the same class, conflicts (e.g. attributes or non-multi methods of the same name) cause a compile-time error, which can be solved by providing a method of the same name in the class.

显然,当 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;

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