如何在 Raku 中删除多方法

tin*_*ino 6 raku nqp

如何使用将在已经定义的方法之前调用的多方法来扩充类?

我试图使负标:@arr[-1]在喜欢这个文章,但不改变源。

所以我用以下方法扩充Array

augment class Array { 
    proto method AT-POS(Array:D: Int:D $i where <0 ) {
        say "AT-POS called";
        my $pos = -1;
        my $ix = $pos + self.elems;
        return self.AT-POS($ix);
    }
};
Run Code Online (Sandbox Code Playgroud)

但正如文档中所述

Please note that adding a multi candidate that differs only
in its named parameters will add that candidate behind the already defined one
and as such it won't be picked by the dispatcher.
Run Code Online (Sandbox Code Playgroud)

所以我的 multi 永远不会被调用:

say .signature for @arr.^method_table{'AT-POS'}.candidates ;
Run Code Online (Sandbox Code Playgroud)
(Any:U \SELF: int \pos, *%_)
(Any:U \SELF: Int:D \pos, *%_)
(Any:U: Num:D \pos, *%_)
(Any:U: Any:D \pos, *%_)
(Any:D: int \pos, *%_)
(Any:D: Int:D \pos, *%_)
(Any:D: Num:D \pos, *%_)
(Any:D: Any:D \pos, *%_)
($: Any:U \pos, *%_)
(Any:D: \one, \two, *%_)
(Any:D: \one, \two, \three, *%_)
(Any:D: **@indices, *%_)
(List:D: int $pos, *%_)
(List:D: Int:D $pos, *%_)
(Array:D: int $pos, *%_)
(Array:D: Int:D $pos, *%_)  # Their
(Array: $a, *%_)
(Array:D: Int:D $pos, *%_)  # My
Run Code Online (Sandbox Code Playgroud)

我希望我的方法在他们之前被调用。如何修改调度器?

Jon*_*ton 9

命名参数不重要;这里没有。问题在于,问题中multi的代码没有添加更具体的候选对象,而是尝试替换proto. 如果改为multi这样添加候选人:

use MONKEY-TYPING;
augment class Array { 
    multi method AT-POS(Array:D: Int:D $i where $i < 0) {
        nextwith($i + self.elems)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,由于where子句的存在,它将在AT-POS没有一个的通常候选人之前被考虑。由于标准候选人仍然适用,nextwith因此可以使用它。使用上面的augment,程序:

my @arr = 1, 2, 3;
my $idx = -1;
say @arr[$idx];
Run Code Online (Sandbox Code Playgroud)

将输出3.

关于augmentapply的常见警告,并且由于每个数组索引操作都将支付此成本,因此预计会显着放缓。

  • 尝试在执行“增强”的模块中添加“无预编译”。 (2认同)