How can I augment a class with a multi-method that will be called before the already defined one ?
I am trying to enable negative subscript: @arr[-1]
like in this article but without changing the source.
So I augment Array with:
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);
}
};
But as stated in the doc
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.
So my multi is never called:
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
I want my method to be called before their. How can can I modify the dispatcher?
Named parameters don't come into the matter; there aren't any here. The problem is that instead of adding a
multi
candidate that is more specific, the code in the question instead tries to replace theproto
. If instead amulti
candidate is added like this:Then, due to the presence of the
where
clause, it will be considered before the usualAT-POS
candidate without one. Since the standard candidate still applies too,nextwith
can be used to defer to it. Using the aboveaugment
, the program:Will output
3
.The usual caveats about
augment
apply, and since every array index operation will pay this cost, expect a significant slowdown.