Weird "Can't use unknown trait" when nextsame or callsame are used
Asked Answered
W

1

6

Here's the program:

my %SUB-COUNTS;

say "Start";

multi sub trait_mod:<is>(Sub $s where .name().contains("-logged"), :$AOP) {
    $s.wrap({
        say "Entering { $s.name }";
        callsame;
    });
}

multi sub trait_mod:<is>(Sub $s where .name().contains("-counted"), :$AOP) {
    $s.wrap({
        say "Counting { $s.name }";
        %SUB-COUNTS{$s.name}++;
    });
}

sub water-logged() is AOP {
    return "Water";
}

sub out-logged() is AOP {
    return "Out";
}

sub we're-counted() is AOP {
    state $count = 0;
    return $count++;
}

sub we're-counted-and-logged() is AOP {
    state $alpha = 'a';
    return $alpha++;
}

say water-logged(), " ", out-logged(), " ", water-logged();

say we're-counted() for ^20;

say we're-counted-and-logged() for ^20;

say %SUB-COUNTS;

This works, but only 1 trait can be applied to every routine, so I've thought about using redispatch so that routines can be counted and logged. However, doing this:

multi sub trait_mod:<is>(Sub $s where .name().contains("-logged"), :$AOP) {
    $s.wrap({
        say "Entering { $s.name }";
        callsame;
    });
    callsame;
}

Results in a weird compile error:

Can't use unknown trait 'is' -> 'AOP' in a sub declaration.
at /home/jmerelo/txt/docencia/presentaciones/aop-raku/code/point-cut.raku:23
    expecting any of:
        rw raw hidden-from-backtrace hidden-from-USAGE pure default
        implementation-detail DEPRECATED inlinable nodal prec equiv
        tighter looser assoc leading_docs trailing_docs

Line 23 is the first declaration that uses AOP. So I'm kind of lost here. How come adding a single statement alter the syntax in such a way?

Wizen answered 25/7, 2021 at 11:7 Comment(0)
C
9

Unfortunately, there is a multi candidate for trait_mod:<is> that reports an error if no matching trait is found. This arguably gives a better error message when one mis-types a trait name than the standard multiple dispatch error against a trait modifier would. However, so far as multiple dispatch is concerned, it's a candidate like any other, and callsame will correctly defer to it.

While it's worth requesting that the better error reporting be done in a way that lacks this side-effect, in the immediate the only solution I can think of is a try around the callsame and suppressing the unknown trait exception.

Clementeclementi answered 25/7, 2021 at 14:3 Comment(2)
But in this case, there would be a candidate, the other multi, right? Why is that candidate called inmediately? Is there a way to change precedence so that the proper one is called?Wizen
It goes to the next applicable candidate; the counted one is only applicable when you have a sub whose name contains both logged and counted. The first sub in your example is sub water-logged() is AOP {, thus the counted one doesn't apply, and so the next most applicable candidate is the error reporting one.Clementeclementi

© 2022 - 2024 — McMap. All rights reserved.