类名在 之后的范围内可用EVALFILE,而文档可能另有说明。
EVALFILE 状态的文档:
Slurps 指定的文件并对其进行评估。在Blob 解码、范围、$lang 参数和 $check 参数方面的行为与EVAL相同。当 $check 不为 True 时,计算文件中最后一条语句产生的值。
EVAL 状态的文档:
由于词法作用域中的符号集在编译后是不可变的,因此EVAL 永远不能将符号引入周围的作用域。
我的输入文件是:
class SomeClass {
method a () { "In SomeClass method a"; };
}
sub some-routine () {
"Some routine";
}
Run Code Online (Sandbox Code Playgroud)
> my $f = EVALFILE("/tmp/eval-bug.raku");
&some-routine
> $f()
Some routine
> some-routine()
===SORRY!=== Error while compiling:
Undeclared routine:
some-routine used at line 1
Run Code Online (Sandbox Code Playgroud)
以上三个执行符合文档,但以下不符合:
> SomeClass.a()
In SomeClass method a
Run Code Online (Sandbox Code Playgroud)
那么符号仅表示例程名称而不是类名称吗?或者这是一个错误?
Jon*_*ton 10
由于词法作用域中的符号集在编译后是不可变的,因此 EVAL 永远不能将符号引入周围的作用域
这里的关键词是“词法范围”。然而,类在默认情况下不是词法范围的(与例程不同),而是包范围。这意味着它们默认引入一个全局名称。如果你改为写:
my class SomeClass {
method a () { "In SomeClass method a"; };
}
Run Code Online (Sandbox Code Playgroud)
然后这声明了一个词法范围的类,不会引入全局名称,因此它不会安装在EVALFILE.
至少对我来说,文档似乎是正确的;它明确提到词法范围,而“周围范围”一词也带有文本(因此是词法)范围界定的含义。但是,它可能会提到EVALFILE将全局安装在 中声明的包范围内的东西。
在我看来,这是两件事的组合:1. 子程序some-routine未导出,以及 2. REPL 中的范围界定问题。
第一个可以通过两种方式修复:
our sub some-routine() {
Run Code Online (Sandbox Code Playgroud)
或者
sub some-routine() is export {
Run Code Online (Sandbox Code Playgroud)
第二个是,在 REPL 的当前状态下,不能真正修复(我已经尝试过,但是我的所有修复都在其他情况下引入了问题)。REPL 当前实现为在EVAL您输入的每一行上执行一个操作,同时尝试EVAL与下一个共享任何先前的元素。在运行时的当前状态下,不可能完全进行共享,这是人们报告的有关 REPL 的许多问题的原因。
在 RakuAST 分支上的工作也意味着让解释器的状态更加“客观化”,如果你愿意的话,允许在EVALs之间更好地共享状态,从而实现更好的 REPL。但这至少还需要几个月的时间才能降落在乐堂。