Raku 能否保证模式匹配是详尽无遗的(在编译时)?
Can Raku guarantee that a pattern match is exhaustive (at compile time)?
考虑以下玩具代码:
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
,甚至 non-deterministic(针对可变对象的智能匹配),则很难或不可能确定.
如果您想对某些条件子集实施这种级别的严格行为,您可以采用类似于以下的解决方法:
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> { ... }
}
考虑以下玩具代码:
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
,甚至 non-deterministic(针对可变对象的智能匹配),则很难或不可能确定.
如果您想对某些条件子集实施这种级别的严格行为,您可以采用类似于以下的解决方法:
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> { ... }
}