rakumop

How do you show the type hierarchy of a value?


In Perl5 and Moose, linear isa or linearized isa helps make sense of class hierarchies.

The method WHAT shows the concrete type of a value:

> 42.WHAT
(Int)

How do I show something like

> 42.hypothetical-type-hierarchy
(Int) ┬ is (Cool) ─ is (Any) ─ is (Mu)
      └ does (Real) ─ does (Numeric)

… possibly with further lines for each consumed role?


edit: example with two strands of roles

class Beta {}
role Delta {}
role Gamma does Delta {}
role Eta {}
role Zeta does Eta {}
role Epsilon does Zeta {}
class Alpha is Beta does Gamma does Epsilon {}

# (Alpha) ┬ is (Beta)
#         ├ does (Gamma) ─ does (Delta)
#         └ does (Epsilon) ─ does (Zeta) ─ does (Eta)

my $ai = Alpha.new
$ai.^mro        # ((Alpha) (Beta) (Any) (Mu))

$ai.^roles      # ((Epsilon) (Zeta) (Eta) (Gamma) (Delta))
                # flat list, not two-element list of a tuple and triple‽

Solution

  • You can query the meta object with

    > 42.^mro
    ((Int) (Cool) (Any) (Mu))
    

    where mro stand for method resolution order and

    > 42.^roles
    ((Real) (Numeric))
    

    You can control which roles are returned via the adverbs :local (exlude roles inherited from parent classes - only available on classes) and :!transitive (exclude roles composed via another role - available on both roles and classes).


    The following should get you started:

    my $depth = 0;
    for Alpha.^mro {
        say "is {.^name}";
        (sub {
            ++$depth;
            for @_ {
                say '  ' x $depth ~ "does {.^name}";
                &?ROUTINE(.^roles(:!transitive)); # recursive call of anon sub
            }
            --$depth;
        })(.^roles(:local, :!transitive));
    }
    

    Given your example code with slight modifications

    role Delta {}
    role Gamma does Delta {}
    role Eta {}
    role Zeta does Eta {}
    role Epsilon does Zeta {}
    class Beta does Gamma {}
    class Alpha is Beta does Gamma does Epsilon {}
    

    it produces the output

    is Alpha
      does Epsilon
        does Zeta
          does Eta
      does Gamma
        does Delta
    is Beta
      does Gamma
        does Delta
    is Any
    is Mu