如何将一个签名测试应用于多个职位

p6s*_*eve 11 units-of-measurement rakudo measure raku

我在https://github.com/p6steve/raku-Physics-Measure中编写了一些代码,在每个数学运算中查找测量类型,并将工作交给非标准方法,这些方法调整单位和误差方面,同时返回新值价值:

multi infix:<+> ( Measure:D $left, Real:D $right ) is export {
    my $result   = $left.clone;
    my $argument = $right;
    return $result.add-const( $argument );
}
multi infix:<+> ( Real:D $left, Measure:D $right ) is export {
    my $result   = $right.clone;
    my $argument = $left;
    return $result.add-const( $argument );
}
multi infix:<+> ( Measure:D $left, Measure:D $right ) is export {
    my ( $result, $argument ) = infix-prep( $left, $right );
    return $result.add( $argument );
}
Run Code Online (Sandbox Code Playgroud)

这个模式对于 <[+-*/]> 重复了 4 次,所以它相当于相当多的样板文件;我想减少一点。

那么,是否有一种更简洁的方法将签名中的单个 Measure|Real 测试应用于两个位置,如果两个或一个匹配但不匹配则触发多重,并且为不妥协的操作 <[ 保留该位置-/]>?

我不确定不使用多重是最优雅的 - 也许只是将 Real-Measure 和 Measure-Real 压缩为 1?

cod*_*ons 10

有几种方法可以解决这个问题,但我可能会做的 \xe2\x80\x93 和一个通常有用的模式 \xe2\x80\x93 是使用一个子来创建一个稍微过度包含的多重,然后重新调度您不应该包含的情况。对于您提供的示例,可能看起来有点像:

\n
subset RealOrMeasure where Real | Measure;\nmulti infix:<+> ( RealOrMeasure:D $left, RealOrMeasure:D $right )  {\n    given $left, $right {\n       when Real,    Real    { nextsame }\n       when Real,    Measure { $right.clone.add-const($left)  }\n       when Measure, Real    {  $left.clone.add-const($right) }\n       when Measure, Measure { my ($result, $argument) = infix-prep $left, $right;\n                               $result.add($argument)}}\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

(注意:我还没有测试过这段代码Measure;如果它不起作用,请告诉我。但总体思路应该是可行的。)

\n

  • 请注意,子集类型是决定性因素,因此使用此方法将影响候选者的排序方式,这可能会导致意外。 (4认同)
  • @raiph例如,比较 `multi m(Int) { 1 }; 多 m(实数) { 2 }; 说 m 1`(标称类型匹配,`Int` 更严格)与 `subset IntSub where Int; 多 m(IntSub) { 1 }; 多 m(实数) { 2 }; 说 m 1`(“子集”意味着“Any”的名义类型,而“Real”更严格)。“proto”方法很可能避免这种情况,但意味着重新调度的成本,并且如果多个模块尝试该策略,则不会组成。 (3认同)
  • `子集 RealOrMeasure 其中 * ~~ Real | Measure;` 不只是 `RealOrMeasure 的子集,其中 Real | 测量;`工作? (2认同)