With this code, I'm trying to add a "logging" trait to a subroutine:
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);
However, I get the error:
===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
(line 14 would be the line where add
is declared). Declaring loggr
directly as a sub yields no error. Why am I getting this Uninstantiable
error here?
Why am I getting this
Uninstantiable
error here?
When used after a my
declaration, =
(or :=
) invokes assignment (or binding) at run-time. A trait applied to a compile-time sub declaration runs at compile-time, which comes first. So your trait calls loggr
before it's initialized.
To fix that, you need to shift the variable initialization to compile-time, eg:
BEGIN &loggr = ...
or
constant &loggr = ...
While the error message reads like a low-level error, and it would be nice if it specifically mentioned loggr
(but perhaps doesn't because it's low-level), it will hopefully make more sense now:
===SORRY!=== Error while compiling ...
Cannot invoke this object (REPR: Uninstantiable; Callable)
Your code has asked to call loggr
at compile-time. But while it does have the appropriate Callable
type, it hasn't yet been initialized, so is uninstantiable at the time it is being asked to invoke it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With