不可实例化;使用特征声明中的 Callable 变量时可调用

jjm*_*elo 5 traits raku

使用此代码,我正在尝试向子例程添加“日志记录”特征:

my &loggr = -> $event {
    state %store;
    %store{ DateTime.new( now ) } = $event;
}

multi sub trait_mod:<is>(Sub $s, :$logger){
    loggr( $s.name );
}

multi sub add( Int $a, Int $b) is logger {
    $a + $b;
}

say add(1,2);
Run Code Online (Sandbox Code Playgroud)

但是,我收到错误:

===SORRY!=== Error while compiling /home/jmerelo/Code/perl6/my-perl6-examples/is-logger-fail.p6
Cannot invoke this object (REPR: Uninstantiable; Callable)
at /home/jmerelo/Code/perl6/my-perl6-examples/is-logger-fail.p6:14
Run Code Online (Sandbox Code Playgroud)

(第 14 行将add是声明的行)。loggr直接声明为 sub 不会产生错误。为什么我在Uninstantiable这里收到这个错误?

rai*_*iph 4

为什么我会Uninstantiable在这里收到此错误?

当在my声明之后使用时,=(或) 在运行时:=调用赋值(或绑定)。应用于编译时子声明的特征在编译时运行,它首先出现。所以你的特质在初始化之前调用。loggr

要解决这个问题,您需要将变量初始化转移到编译时,例如:

BEGIN &loggr = ...
Run Code Online (Sandbox Code Playgroud)

或者

constant &loggr = ...
Run Code Online (Sandbox Code Playgroud)

虽然错误消息读起来像是一个低级错误,如果特别提到它会很好loggr(但可能没有,因为它是低级错误),但现在希望它更有意义:

===SORRY!=== Error while compiling ...
Cannot invoke this object (REPR: Uninstantiable; Callable)
Run Code Online (Sandbox Code Playgroud)

您的代码要求loggr在编译时调用。但是,虽然它确实具有适当的Callable类型,但它尚未初始化,因此在要求调用它时是不可实例化的。