让perl6调用由subtype(subset)专门化的正确的multi sub

时间:2019-01-23 10:24:38

标签: perl6 subtype multidispatch

我有一个类型层次结构,该层次结构由perl6的subset命令和一些专门针对这些类型的多重子对象构成。发生多调度时,如何赋予最窄子类型所特有的子优先级?

这是简化的代码:

#! /usr/bin/env perl6

use v6.c;

proto check($value) { * }

subset Positive of Int where * > 0;

subset PositiveEven of Positive where * %% 2;

multi check(Int $value) {
    say "integer"
}

multi check(Positive $value) {
    say "positive"
}

multi check(PositiveEven $value) {
    say "positive & even"
}

# example:
check(32);

# expected output:
#   positive & even

# actual output:
#   positive 

2 个答案:

答案 0 :(得分:10)

由于所有候选者都同样紧,因此将采用与其余约束(或缺少约束)匹配的第一个。这是在其中指定多个候选项的顺序变得重要的时候。如果您将按以下顺序指定它们:

multi check(PositiveEven $value) { say "positive & even" }
multi check(Positive $value) { say "positive" }
multi check(Int $value) { say "integer" }

以下发挥您的期望:

check(32);   # positive & even

答案 1 :(得分:5)

主要问题是子集实际上不是类型,而只是约束。 如果你这样做

say :(PositiveEven $value).perl;
say :(Positive $value).perl;
say :(Int $value).perl;

您将获得

:(Int $value where { ... })
:(Int $value where { ... })
:(Int $value)

尽管最新的一个明显不同,但是其他两个在签名方面没有区别,因此使用发现的第一个。您将需要将它们声明为类,或者找到其他通过签名区分它们的方法,或者使用nextsame

在子程序内部
proto check($value) { * }

subset PositiveEven of UInt where * %% 2;

multi check(Int $value) {
    say "integer"
}

multi check(UInt $value) {
    if $value ~~ PositiveEven {
    nextsame;
    }
    say "positive"
}

multi check(PositiveEven $value) {
    say "positive & even"
}

这将按预期返回positive & even。您甚至不需要将最后一个子变量的arg定义为PositiveEven,但是可以出于参考目的将其保留在那里。