Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uninstantiable; Callable when using Callable variables from a trait declaration

Tags:

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?

like image 435
jjmerelo Avatar asked Jun 09 '18 08:06

jjmerelo


1 Answers

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.

like image 76
raiph Avatar answered Sep 28 '22 06:09

raiph