perl6通过子类型(子集)调用正确的多子专用

lov*_*ato 10 perl6 subtype multidispatch

我有一个用perl6的子集命令构造的类型层次结构,以及一些专门针对这些类型的多子类.当多调度发生时,如何通过最窄的子类型赋予最高优先级?

这是简化的代码:

#! /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 
Run Code Online (Sandbox Code Playgroud)

Eli*_*sen 10

由于所有候选人都同样紧张,因此第一个候选人将与其他约束(或缺少约束)相匹配.这是指定多候选者的顺序变得重要的时候.如果您按此顺序指定它们:

multi check(PositiveEven $value) { say "positive & even" }
multi check(Positive $value) { say "positive" }
multi check(Int $value) { say "integer" }
Run Code Online (Sandbox Code Playgroud)

以下将满足您的期望:

check(32);   # positive & even
Run Code Online (Sandbox Code Playgroud)


jjm*_*elo 5

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

say :(PositiveEven $value).perl;
say :(Positive $value).perl;
say :(Int $value).perl;
Run Code Online (Sandbox Code Playgroud)

你会得到的

:(Int $value where { ... })
:(Int $value where { ... })
:(Int $value)
Run Code Online (Sandbox Code Playgroud)

虽然最新的一个明显不同,但其他两个在签名方面没有区别,因此使用了第一个.您需要将它们声明为类或者找到另一种方法来通过签名区分它们,或者使用nextsame在sub本身内部

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"
}
Run Code Online (Sandbox Code Playgroud)

这将按positive & even预期返回.您甚至不需要将最后一个sub的arg定义为PositiveEven,但是可以将其留在那里以供参考.