You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raku中运行时创建的符号在PseudoStash与EVAL中不可用问题问询

问题背景

我最初尝试排查运行时创建的符号无法被EVAL访问的问题。

outer-EVAL.raku

#!/usr/bin/env raku

use MONKEY-SEE-NO-EVAL;

package Foobar {
  our $foo = 'foo';

  our sub eval {
    say OUTER::;
    EVAL "say $bar";
  }
}

Foobar::<$bar> = 'bar';
say $Foobar::bar;

Foobar::eval;

.say for Foobar::;

运行报错:

$ ./outer-EVAL.raku 
===SORRY!=== Error while compiling /development/raku/VTS-Template.raku/scratchpad/./outer-EVAL.raku
Variable '$bar' is not declared
at /development/raku/VTS-Template.raku/scratchpad/./outer-EVAL.raku:10
------>     EVAL "say ⏏$bar";

我推测该问题和这类方式创建的符号在PseudoStash中不可用有关,但我也不确定是否正确。

outer.raku

#!/usr/bin/env raku

package Foobar {
  our $foo = 'foo';

  our sub outer {
    say OUTER::;
  }
}

Foobar::<$bar> = 'bar';
say $Foobar::bar;

Foobar::outer;

.say for Foobar::;

运行结果:

$ ./outer.raku 
bar
PseudoStash.new(($?PACKAGE => (Foobar), $_ => (Any), $foo => foo, &outer => &outer, ::?PACKAGE => (Foobar)))
&outer => &outer
$bar => bar
$foo => foo

如运行结果所示,$Foobar::bar存在于Foobar::的Stash中,但不在OUTER::对应的PseudoStash里。因此我有两个疑问:

  • 为什么运行时创建的符号无法被EVAL访问?
  • 为什么运行时创建的符号在PseudoStash中不可用?

解答

首先你遇到的第一个编译报错和EVAL本身、动态符号都无关,是字符串插值的低级错误:你给EVAL传的是双引号包裹的字符串,Raku编译外层代码时会先对双引号内的$bar做变量插值,此时$bar在Foobar::eval的词法作用域中没有定义,所以还没到EVAL运行阶段,外层代码的编译就直接失败了。

把双引号换成单引号避免提前插值,再给EVAL指定包上下文即可正常访问动态创建的符号:

#!/usr/bin/env raku
use MONKEY-SEE-NO-EVAL;
package Foobar {
  our $foo = 'foo';
  our sub eval {
    # 单引号避免提前插值,指定PACKAGE参数让EVAL在Foobar包上下文编译代码
    EVAL 'say $bar', :PACKAGE(Foobar);
  }
}
Foobar::<$bar> = 'bar';
Foobar::eval; # 正常输出 bar

关于PseudoStash的问题:PseudoStash是编译期生成的作用域快照,在你定义Foobar::outer、Foobar::eval这些子例程的时候,Raku编译器已经捕获了当时Foobar包的符号表状态,生成对应的PseudoStash实例绑定到这些子例程的OUTER::上下文。后续你在运行时动态往Foobar的Stash里添加$bar,只会更新包的实际符号表,不会回溯修改之前已经生成的所有PseudoStash实例,所以你在子例程中打印OUTER::时看不到后续添加的动态符号。


内容的提问来源于stack exchange,提问作者JustThisGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:48:02