Raku 能否保证模式匹配是详尽的(在编译时)?

cod*_*ons 5 pattern-matching compile-time 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»
Run Code Online (Sandbox Code Playgroud)

此代码包含导致运行时错误的错误(不处理输入正好为 18 的情况)。有没有办法通过要求given块完全匹配来在编译时捕获此错误?它看起来像有应该使用的方式CHECK移相器或类似的东西,要求匹配是详尽的,但我不能肯定我怎么会去这样做。

(我知道您可以在运行时通过抛出错误的情况更早地捕获default错误,但这不是我要问的问题。如果 Raku 没有办法在编译时强制执行详尽匹配,那也不是什么大缺点语言 - 但它可能是一个有用的功能。)

use*_*601 6

虽然您可以编写一个模块来强制执行这些内容(尤其是在 RakuAST 出现时),但它会处理给定的语句,这将非常棘手,并且实际上只能用于基本的数值运算。

given/的语义when基本上是

given $foo {         # topicalize $foo
    when $bar1 { … } #   if    $foo ~~ $bar1
    when $bar2 { … } #   elsif $foo ~~ $bar2
    when $bar3 { … } #   elsif $foo ~~ $bar3
    default    { … } #   else 
}
Run Code Online (Sandbox Code Playgroud)

如果您的条件是复杂的东西,例如.is-primeand * %% 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>   { ... }
}
Run Code Online (Sandbox Code Playgroud)