ModuleA有一个成员变量名为c
,带有WHERE子句:
unit class A;
my MAXVALUE = 1000_000;
has $.c where 0 < * < MAXVALUE;
method gist() {
"$!c";
}
<设置strong>RAKULIB 环境变量:设置strong>
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
表达式中,将在编译时计算。
{ ... }
语法),那么可能不是的情况。如果代码中的行:
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