问题描述
请考虑以下玩具代码:
my $age-check = do given 18 {
when $_ > 18 { 'old enough' }
when $_ < 18 { 'too young' }
};
say "The user is $age-check" # OUTPUT: «The user is False»
此代码包含一个导致运行时错误的错误(无法正确处理输入为18的情况)。是否有任何方法可以通过要求given
块完全匹配来在编译时捕获此错误?似乎应该有一种使用CHECK
移相器或类似的方法来要求匹配详尽无遗的方法,但我不太确定该怎么做。
(我知道您可以在运行时使用default
案例捕获错误更早,该案例引发错误,但这不是我要的问题。如果Raku没有一种在编译时强制进行详尽匹配的方法,这并不是该语言的主要缺点-但这可能是一个有用的功能。)
解决方法
虽然您可以编写模块来通过处理给定的语句来强制执行此操作(尤其是RakuAST一旦出现),但这将非常棘手,并且实际上仅适用于基本数值运算。
given
/ when
的语义基本上是
given $foo { # topicalize $foo
when $bar1 { … } # if $foo ~~ $bar1
when $bar2 { … } # elsif $foo ~~ $bar2
when $bar3 { … } # elsif $foo ~~ $bar3
default { … } # else
}
如果您的条件很复杂,例如.is-prime
和* %% 2
,甚至是不确定性(针对可变对象的智能匹配),那么肯定很难或不可能知道。
如果您想对某些条件子集强制执行此级别的严格行为,则可以执行类似以下的解决方法:
sub is-exhaustive(@conditions) {
... # complex algorithm to determine that the conditions are exhaustive
}
my %foo =
less-than-eighteen => * < 18,more-than-eighteen => * > 18,exactly-eighteen => * == 18;
CHECK die unless is-exhaustive %foo.values;
given $bar {
when %foo<less-than-eighteen> { ... }
when %foo<more-than-eighteen> { ... }
when %foo<exactly-eighteen> { ... }
}