无法在CLASS中使用WHERE子句中的无符号变量?



ModuleA有一个成员变量名为c,带有WHERE子句:

unit class A;
my MAXVALUE = 1000_000;
has $.c where 0 < * < MAXVALUE;
method gist() {
"$!c";
}

<设置strong>RAKULIB 环境变量:

set RAKULIB="d:scriptsRakuAlib"      # Windows
export RAKULIB="/opt/scripts/Raku/A/lib" # Linux

像这样使用模块A:

use A;
my $a = A.new(c => 1);
say $a;

但是得到类型检查错误:

Type check failed in binding to parameter '<anon>'; expected Any but got Mu (Mu)
in whatevercode  at D:scriptsRakuRakuAlib.precompC6EB86CB837D3BCAAA3D85B66CE337C820700C086D6DCD4CE23D88E2EE9568BA546C007C63D9131C1B line 1
in block <unit> at basic.rakutest line 3

这是一个bug吗?

乐烧版本:

raku -v
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.

打到:BEGIN say 1 < Mu显示基本相同的错误信息。

在您的代码中,MAXVALUE在编译时被初始化为值Mu。你必须修改你的代码,使... < MAXVALUE的求值出现在MAXVALUE被初始化为非Mu的值之后。

在这个答案的其余部分:

  • 最简单的编译时间解决方案是什么?

  • 如果您想使用运行时值该怎么办?

  • 幕后发生了什么?

  • 错误信息是LTA吗?

最简单的编译时间解决方案是什么?

你自己在这个答案下面的评论中提供了一个很好的编译时间解决方案,作为对我第一个版本的回应。

也就是说,如果您希望保持符号纯粹的词法作用域,您应该从my: 开始
my constant MAXVALUE = 1000_000;

问题解决了。

如果想使用运行时值该怎么办?

where子句中的变量/符号/表达式如果在WhateverCode表达式中,将在编译时计算

但是如果您使用lambda(使用{ ... }语法),那么可能不是的情况。如果代码中的行:
has $.c where 0 < * < MAXVALUE;

更改为:

has $.c where { 0 < $_ < MAXVALUE }

那么你的代码就可以工作了。

但是…

如果你在has行添加一个显式的初始值…

has $.c where { 0 < $_ < MAXVALUE } = 10;
^^^^ Explicit initialization

…那么错误将返回,因为现在where子句在编译期间由于连锁反应而被调用:

  • 编译器决定检查初始化值是否通过where检查

  • 编译器在编译时计算where子句;

  • 这反过来导致MAXVALUE被求值——并且它在编译时包含Mu,导致错误返回。

幕后发生了什么?

初始化has变量有编译时和运行时两个阶段:

  • 编译时,当正在组成时,确定实例将为每个has变量具有的默认值。三种常见的场景是:

    tbody> <<tr>
    has语句默认值
    has $foo;Any
    has $foo where some-condition;<anon>
    has $foo = 42;42

相关内容

  • 没有找到相关文章

最新更新