Raku是否可以保证模式匹配是详尽无遗的在编译时?

问题描述

请考虑以下玩具代码

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>   { ... }
}