首页 > 解决方案 > 如何在 Raku 中删除多方法

问题描述

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

我正在尝试启用负下标:@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);
    }
};

但正如文档中所述

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.

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

say .signature for @arr.^method_table{'AT-POS'}.candidates ;
(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

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

标签: rakunqp

解决方案


命名参数不涉及问题;这里没有。问题在于,问题中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)
    }
}

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

my @arr = 1, 2, 3;
my $idx = -1;
say @arr[$idx];

会输出3

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


推荐阅读