Disecting subsets
While fighting with htmlily.p6 I found myself in need of a tool that shows me the structure of a pod6 file. Since all nodes are subclasses of Pod::Block and it’s tree structure is walked through simply by recursively descending into .contents, it was easily done. Just recurse and print .^name with some indentation. Putting a stack on walks back is needed because Pod::Block doesn’t provide a .parent method. A bit ugly but not really a problem.
What did confuse me was the fact that .^name on subsets that provide Pod::FormattingCode with a better name didn’t carry a proper type name. And in fact, a subset does inject a new name into the scope but does not change the type of an object that passed a type check against it.
subset FooStr of Str; my FooStr $s; sub f(FooStr $s){ say $s.^name }; f("abc"); # OUTPUT«Str»
That is fine if you want to use a subset as a type check. Since it passed the check, it must be of that type or a type that behaves in the same way.
I wanted to do introspection, what means turning a type object into a name. Even worse I wanted to turn a type object into a name of a type that is narrower. Since there is no reference from a type to all its sub types, Perl 6 could not help me there. At least not directly.
Luckily I put the subsets into a inline package. When you stick Foo::Bar::
in front of a name, Perl 6 will kindly generate a package for you and put the new types inside. Since a package is a Stash with a funky name, we can iterate over it’s key-value-Pairs. The keys are names and the values are type objects.
Pod::FormattingCode::.pairs.first({ $node ~~ $^a.value }).key
In my case there is a 1:1 relationship between a subset and it’s base type properties, so I can be sure that the first match is correct.
A nice example how using common data structures in the language implementation and exposing them to the programmer, can help Perl 6 to help you.
-
July 18, 2016 at 23:292016.29 The Zoffix Has Landed | Weekly changes in and around Perl 6