Golfed to: BEGIN say 1 < Mu 显示基本相同的错误消息。
在您的代码中,MAXVALUE 在编译时使用值 Mu 进行初始化。您必须更改您的代码,以便对... < MAXVALUE 的评估在 MAXVALUE 已初始化为具有Mu 以外的值。
在这个答案的其余部分:
-
什么是最简单的编译时解决方案?
-
如果您想使用运行时值怎么办?
-
幕后发生了什么?
-
错误信息是 LTA 吗?
什么是最简单的编译时解决方案?
您自己在此答案下方的评论中提供了一个很好的编译时解决方案,以响应我的第一个版本。
也就是说,如果您希望符号保持纯粹的词法范围,您应该以 my 开头:
my constant MAXVALUE = 1000_000;
问题解决了。
如果您想使用运行时值怎么办?
如果where 子句中的变量/符号/表达式位于WhateverCode expression 中,将在编译时评估。
但如果您使用 lambda(使用 { ... } 语法)代替,可能就不是这样了。如果代码中的行:
has $.c where 0 < * < MAXVALUE;
改为:
has $.c where { 0 < $_ < MAXVALUE }
那么你的代码就可以工作了。
但是...
如果您向has 行添加显式初始值...
has $.c where { 0 < $_ < MAXVALUE } = 10;
^^^^ Explicit initialization
...然后错误会返回,因为现在where 子句由于链式反应在编译期间被调用:
幕后发生了什么?
初始化has变量有编译期和运行期两个阶段:
以下代码旨在演示该过程:
BEGIN say 'code compile-time, start, outside class';
say 'code run-time, start, outside class';
sub init (*%_) { say "initializing {|%_}" }
class foo {
has $.bar;
has $.baz where init(baz => $_);
has $.buz where init(buz => $_) = 42;
say 'run-time, at end of class';
BEGIN say 'compile-time, at end of class';
}
BEGIN say 'compile-time, outside class again';
say 'run-time, outside class again';
say foo.new(buz => 99);
显示:
code compile-time, start, outside class
compile-time, at end of class
initializing buz 42
compile-time, outside class again
code run-time, start, outside class
run-time, at end of class
run-time, outside class again
initializing buz 99
foo.new(bar => Any, baz => <anon>, buz => 99)
注意完整构建实例中三个has 变量的完整初始化:
-
bar => Any.
这是变量的通常默认初始化。
-
baz => <anon>.
cfsay my Int $var;显示(Int),因为有类型约束但没有显式初始化值的变量的默认值是类型约束对应的类型对象,而say my $var where 1;显示(<anon>),反映where 约束的匿名性质(与 subset 相比)。所以has $.baz where init(baz => $_); 的默认值是(<anon>)。
-
buz => 99.
这是显示initializing ... 行的唯一has 变量——重要的是,有两行行,而不是一行:
-
first 行立即显示在compile-time, at end of class 之后,即当编译器到达类声明的结束花括号时。这是 Raku 进行类组合的时候,buz 获取默认值 42。
-
然后,在评估foo.new(buz => 99);(在运行时构建类的实例时,出现initializing 99。
错误信息是 LTA 吗?
在这个答案的第一个版本中,我写道:
我自己无法提供一个连贯的解释......它是否被认为是一个错误。我目前确实考虑错误消息 LTA。
现在是我仔细讨论错误消息的时候了:
Type check failed in binding to parameter '<anon>'; expected Any but got Mu (Mu)
in whatevercode at ... A\lib ... line 1
in block <unit> at ... line 3
-
Type check failed ...
where 检查失败。它被称为“类型检查”。鉴于 Raku 对“类型”一词的正常使用,我认为这很好。
-
... in binding to parameter '<anon>';
我不确定“参数”指的是什么,也不确定'<anon>'。 Imhh(在我的谦虚假设中)“参数”指的是infix:«<» 函数的参数,'<anon>' 指的是在运行时尝试匿名where 约束之前在编译时存储在$.c 中的值。
LTA?也许像 <where clause> 而不是 <anon> 这样的东西可行且合适?
-
expected Any but got Mu (Mu)
默认情况下,has 变量需要Mu,而不是Any。所以这条消息似乎不是指的是$.c。所以,就像我关于“参数”的假设一样,我认为这是关于 infix:«<» 函数的一个参数。
这是非常有用的信息。任何时候你看到but got Mu (Mu),你都可以确定初始化某些值失败是问题的一部分,这里确实是这种情况。
-
in whatevercode
爆炸发生在WhateverCode,所以这部分对于知道WhateverCode 是什么的人很有用。
LTA?如果有人不知道WhateverCode 是什么,这部分很神秘。我认为in WhateverCode 而不是in whatevercode 将是一个值得改进的地方。也许in WhateverCode (eg '* < 42'),'*
-
at ... A\lib ...
我省略的路径部分 (...) 既有用(完整)又糟糕(长的非人类友好字符串)。
LTA?或许将路径移至终点会有所帮助:
Type check failed ... got Mu (Mu)
in whatevercode at A\lib line 1
(Full path to A\lib: D:\scripts\Raku\Raku\A\lib\.precomp\
C6EB86CB837D3BCAAA3D85B66CE337C820700C08\
6D\6DCD4CE23D88E2EE9568BA546C007C63D9131C1B)
-
... line 1
“line 1”大概是指whatevercode 中的第1 行或A\lib 中的第1 行。无论哪种方式,它都不是特别有用。
LTA? 让第 1 行所指的内容更清楚是可行且适当的,如果它指的是A\lib,则使其准确指向whatevercode。
-
in block <unit> at line 3
这很有用。