D和D:?之间的区别是什么?

时间:2016-02-15 21:31:37

标签: perl6 raku

我正在浏览Perl 6 docs on the shift routine并看到了这个片段:

  

定义为:

multi sub    shift(Array:D )
multi method shift(Array:D:)

我知道:D表示Arraydefined而不是AnyNil,但:D:是什么?它很难搜索。

类型签名文档的

This section包含更多语法示例,但不(据我所知)解释它。

2 个答案:

答案 0 :(得分:13)

方法的调用作为隐式的第一个参数传递。如果您想在签名中使用显式参数(例如,添加类型为:D的笑脸,或者只是为了给它提供更具描述性的名称),则需要将其与:分开,而不是来自参数列表其余部分的,。即使在列表为空的情况下也是如此,因此可以从具有常规位置参数的签名中消除歧义。

可以找到更多信息in the design documents

答案 1 :(得分:4)

Christoph的答案已经很好。我的答案是尝试通过一个小的具体示例提供一些背景信息。

如克里斯托弗(Christoph)所述,在Raku中,方法的调用者作为隐式的第一个位置参数传递,然后以self的形式供该方法的主体使用:

class Person {
    has $.name;

    method greet( Person $B, $greeting = 'Hello' ) {
        $A.name ~ ": $greeting, " ~ $B.name ~ '.'
    }
}

my $john = Person.new(name => 'John');
my $dana = Person.new(name => 'Dana');
say $john.greet($dana, 'Good morning'); # «John: Good morning, Dana.»

如果希望将其绑定到其他对象,请使用语法method meth-name( invocant : param1, param2, ..., param3) { ... },其中param1, param2, ..., param3是您在方法中声明的常规参数(位置参数和命名参数)。正如克里斯托夫(Christoph)所言,这种语法“即使在[无Parparmer签名]的情况下也是必要的,因此可以将其与带有常规位置参数的签名区分开。”因此:

# Person A greets person B.
method greet( $A : Person $B, $greeting = 'Hello' ) {
    self.name ~ ": $greeting, " ~ $B.name ~ '.'
}

您可以走得更远,也可以键入请求者,这不一定是因为需要它,而是因为它使方法的签名更具描述性:

# Person A greets person B.
method greet( Person $A : Person $B, $greeting = 'Hello' ) {
    $A.name ~ ": $greeting, " ~ $B.name ~ '.'
}

如果您不希望方法greet接受类型对象(例如Person),而只接受类型(例如Person.new)的对象实例,则可以利用类型 笑着 :D。因此:

# Person A greets person B.
method greet( Person:D $A : Person $B, $greeting = 'Hello' ) {
    $A.name ~ ": $greeting, " ~ $B.name ~ '.'
}

type smilies:D(对于 D 定义),:U(对于 U 未定义)和{{1 }}(这是既不使用:_也不使用:D的类型的隐含笑容)。

如果从方法的签名中删除显式调用者(并恢复为使用:U),则最终将得到与问题类似的内容。在这里,我只是使用一些空格使它看起来不那么令人生畏:

self

附录:

在Raku中,可以将方法限制为只能在类的对象实例上(对于 object方法)或仅在类本身上(对于 class方法)被调用。 ;您只需将method greet( Person:D : Person $B, $greeting = 'Hello' ) { self.name ~ ": $greeting, " ~ $B.name ~ '.' } smily添加到对象方法的类名中,并将:D smily添加到类方法的类名中

:U

但是,这并不像一般的那么普遍,您可以使用编译时变量::?CLASS来确定当前类,从而消除了将类名放在此处的需要。例如,限制method object-method( CLASSNAME:D : ) { ... } method class-method( CLASSNAME:U : ) { ... } 仅在greet的实例对象上调用:

Person

就像总是被冒号弄糊涂一样,您总是可以在smily所附加的任何东西和其余的method greet( ::?CLASS:D: Person $B, $greeting = 'Hello' ) { self.name ~ ": $greeting, " ~ $B.name ~ '.' } 之间放置一些空格,以使情况更加明显,例如:

: