2017-01-22 51 views
8

想象一系列表示爲角色複雜的語法,雖然這個簡單的例子就足以表明衝突:Perl 6應該能夠解開來自不同來源的相同角色的包含嗎?

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不理清的關係弄清楚,衝突實際上是從同一來源同樣的事情:

法「阿爾法」必須由類啄,因爲它存在於多個角色

但是,讀0123可以解決,我看到:

角色不能從類繼承,但可能由其他角色組成。然而,這個「crony」作文在課程結構時間之前不會被評估。這意味着如果兩個角色引入了同一個配對,那麼就沒有衝突 - 就好像這個類自己扮演了角色的角色,而且各個角色都沒有。不管其合併方式如何,角色可能永遠不會與自己發生衝突。

我讀到意味着角色被儘可能晚地應用,因此該類Thingy將能夠解開這Alpha包括在兩個不同的部分。我想這可能會像創建一個組成最終類的所有角色列表,然後將該列表僅應用於最終類。那樣的話,像Either這樣的東西只會混合它所定義的東西,並且會依靠後面的組合來引入Alpha

當我試圖爲各種(IETF)RFC實現語法時遇到了這個問題。其中許多引用了其他RFC的語法,這使得Perl 6無法通過C3解決繼承問題。所以,我認爲角色會斷開關係。顯然它沒有。

+0

這是否有什麼特別的語法?下面的失敗與預期相同(和預期的一樣):'perl6 -e'role Foo {method bar {}};角色Baz {方法欄{}}; class My :: Grammar {也是Foo;巴茲也是; }'' 否則,你當然可以自己解決它(在文檔中提到的角色):'token Host {$ = [' :'<.port>]? }' – ugexe

+0

這對於語法來說並不是特定的,但是對於可以在語法的幾個部分中顯示的命名規則來說,它更有用。我寧願不自己解決問題,因爲當語法龐大時,這是一個巨大的混亂。 –

+2

標題問題的答案是「是的,應該的」。 –

回答

3

是的,Perl 6應該能夠解開來自不同來源的相同角色的包含。

簡單definitionrole的是:

角色封裝了一些片行爲或狀態,可以類之間被共享。

角色是對行爲的離散集合的名稱。

所以,讓我們說我們有一個Floatable行爲,可以在水面上浮動的物體,和Sailable行爲對象可以航行。當然,可以航行的物體可以漂浮。 A Sloop自然可以浮動和可運輸。行爲由FloatableSailable角色傳遞的事實不存在衝突。

在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時,我注意到

的一個問題是缺少一個簡單的,一個句子的定義:

角色是類似於類的一些方法,因爲它們的屬性和方法的集合。它們的區別在於角色也僅用於描述對象行爲的一部分以及角色如何應用於類。或者用不同的方式來描述它,類是用於管理對象的,角色用於管理行爲和代碼重用。

...

角色從應用類繼承顯著不同。將角色應用於類時,該角色的方法將被複制到類中。如果將多個角色應用於同一個類,則衝突(例如,屬性或同名多個非方法)會導致編譯時錯誤,這可以通過在類中提供同名方法來解決。

顯然,當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; 

在這種情況下,衝突是可以預料的,因爲兩個不同的角色要聲明提供相同的行爲。

相關問題