Three ways to pretty print Perl 6

I’ve had my head down working on the “Grammars” chapter, and along
the way I’ve been using dd to look at things. It’s better than nothing, but it’s also very compact and unwrapped. I really wanted a pretty printer, and I was even prepared to write my own. But, I don’t have to. Here are three modules that can do it for you.

But Jeff Goff has already written Pretty::Printer. I wasn’t able to install it with panda or zef (and it’s not listed on modules.perl6.org). But, you can get it from the perl6-pp GitHub repo.

Here’s a structure that I want to inspect. It includes a Match object with a named capture:

use v6;
use lib qw/lib/;

my $match = ('123456789' ~~ m:g/$<digit>=(\d+:)/);

my %hash =
	dog => 'Nikki',
	cat => 'Buster',
	butterfly => 'Hamadryas',
	array => [ 5 .. 10 ],
	complex => {
		one => 37,
		two => "Buster",
		three => [ 3..7 ],
		four => {
			array => [ 4..7 ],
			hash  => {
				dog => 'Newfie',
				}
			},
		},
	match => $match;
	;

I can use the built-in dd to get this very compact representation that just needs whitespace in the right places:

Hash %hash = {:array($[5, 6, 7, 8, 9, 10]), :butterfly("Hamadryas"), :cat("Buster"), :complex(${:four(${:array($[4, 5, 6, 7]), :hash(${:dog("Newfie")})}), :one(37), :three($[3, 4, 5, 6, 7]), :two("Buster")}), :dog("Nikki"), :match($(Match.new(ast => Any, list => (), hash => Map.new((:digit(Match.new(ast => Any, list => (), hash => Map.new(()), orig => "123456789", to => 9, from => 0)))), orig => "123456789", to => 9, from => 0),))}

With Pretty::Printer (using the pull request I just sent), I can choose some formatting options:

use Pretty::Printer;

my $pp = Pretty::Printer.new(
	pre-item-spacing       => "\n",
	post-item-spacing      => "\n",

	intra-group-spacing    => "",

	pre-separator-spacing  => '',
	post-separator-spacing => "\n",

	indent-style           => "   ",
	);

say $pp.pp( %hash );

The output is a bit rough, but it’s much easier for me to read, especially with the match stuff:

${
   :array($[
      5,
      6,
      7,
      8,
      9,
      10
   ]),
   :butterfly("Hamadryas"),
   :cat("Buster"),
   :complex(${
      :four(${
         :array($[
            4,
            5,
            6,
            7
         ]),
         :hash(${
            :dog("Newfie")
         })
      }),
      :one(37),
      :three($[
         3,
         4,
         5,
         6,
         7
      ]),
      :two("Buster")
   }),
   :dog("Nikki"),
   :match($(
         Match.new(${
                    :ast(Any),
                    :from(0),
                    :hash(Map.new(
                       :digit(Match.new(${
                              :ast(Any),
                              :from(0),
                              :hash(Map.new()),
                              :list($()),
                              :orig("123456789"),
                              :to(9)
                       })))),
                    :list($()),
                    :orig("123456789"),
                    :to(9)
         })
   ))
}

There’s also Data::Dump (which you can install with panda:

use Data::Dump;
say Dump %hash;

I find the output is a bit too detailed for most of my needs, but does fine with the Match object. Although you can’t see it here, the output can be colored if your terminal supports that:

{
  array     => [
    5.Int,
    6.Int,
    7.Int,
    8.Int,
    9.Int,
    10.Int,
  ],
  butterfly => "Hamadryas".Str,
  cat       => "Buster".Str,
  complex   => {
    four  => {
      array => [
        4.Int,
        5.Int,
        6.Int,
        7.Int,
      ],
      hash  => {
        dog => "Newfie".Str,
      },
    },
    one   => 37.Int,
    three => [
      3.Int,
      4.Int,
      5.Int,
      6.Int,
      7.Int,
    ],
    two   => "Buster".Str,
  },
  dog       => "Nikki".Str,
  match     => [
    Match :: (
      $!CURSOR => undefined,
      $!from  => 0.Int,
      $!made  => (Any),
      $!orig  => "123456789".Str,
      $!to    => 9.Int,
      %!hash  => {
        digit => Match :: (
          $!CURSOR => undefined,
          $!from  => 0.Int,
          $!made  => (Any),
          $!orig  => "123456789".Str,
          $!to    => 9.Int,
          %!hash  => { },
          @!list  => [ ],

          method ACCEPTS () returns Mu {...},
          method BUILD (:@list, :%hash) returns Nil {...},
          method Bool () returns Mu {...},
          method Bool () returns Mu {...},
          method CURSOR () returns Mu {...},
          method Capture () returns Mu {...},
          method FLATTENABLE_HASH () returns Mu {...},
          method FLATTENABLE_LIST () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Method+{}.new () returns Mu {...},
          method Numeric () returns Mu {...},
          method Numeric () returns Mu {...},
          method Str () returns Mu {...},
          method Str () returns Mu {...},
          method WHICH () returns Mu {...},
          method ast () returns Mu {...},
          method caps () returns Mu {...},
          method chunks () returns Mu {...},
          method elems () returns Mu {...},
          method from () returns Mu {...},
          method from-args () returns Mu {...},
          method gist () returns Mu {...},
          method gist () returns Mu {...},
          method hash () returns Mu {...},
          method list () returns Mu {...},
          method made () returns Mu {...},
          method make (Mu \made) returns Mu {...},
          method new (:$orig, :$from, :$to, :$CURSOR, :$made) returns Mu {...},
          method new (:@list, :%hash) returns Mu {...},
          method orig () returns Mu {...},
          method perl () returns Mu {...},
          method perl () returns Mu {...},
          method postmatch () returns Mu {...},
          method prematch () returns Mu {...},
          method to () returns Mu {...},
        ),
      },
      @!list  => [ ],

      method ACCEPTS () returns Mu {...},
      method BUILD (:@list, :%hash) returns Nil {...},
      method Bool () returns Mu {...},
      method Bool () returns Mu {...},
      method CURSOR () returns Mu {...},
      method Capture () returns Mu {...},
      method FLATTENABLE_HASH () returns Mu {...},
      method FLATTENABLE_LIST () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Method+{<anon|140185815714976>}.new () returns Mu {...},
      method Numeric () returns Mu {...},
      method Numeric () returns Mu {...},
      method Str () returns Mu {...},
      method Str () returns Mu {...},
      method WHICH () returns Mu {...},
      method ast () returns Mu {...},
      method caps () returns Mu {...},
      method chunks () returns Mu {...},
      method elems () returns Mu {...},
      method from () returns Mu {...},
      method from-args () returns Mu {...},
      method gist () returns Mu {...},
      method gist () returns Mu {...},
      method hash () returns Mu {...},
      method list () returns Mu {...},
      method made () returns Mu {...},
      method make (Mu \made) returns Mu {...},
      method new (:$orig, :$from, :$to, :$CURSOR, :$made) returns Mu {...},
      method new (:@list, :%hash) returns Mu {...},
      method orig () returns Mu {...},
      method perl () returns Mu {...},
      method perl () returns Mu {...},
      method postmatch () returns Mu {...},
      method prematch () returns Mu {...},
      method to () returns Mu {...},
    ),
  ],
}

And, there’s Data::Dump::Tree, which is also colorized.

use Data::Dump::Tree;
say dump %hash;

It might be more comfortable for people used to the Microsoft hierarchical interfaces, but notice how it’s not that interesting for Match objects:

{6} @0
├ array => [6] @1
│ ├ 0 = 5.Int
│ ├ 1 = 6.Int
│ ├ 2 = 7.Int
│ ├ 3 = 8.Int
│ ├ 4 = 9.Int
│ └ 5 = 10.Int
├ butterfly => Hamadryas.Str
├ cat => Buster.Str
├ complex => {4} @2
│ ├ four => {2} @3
│ │ ├ array => [4] @4
│ │ │ ├ 0 = 4.Int
│ │ │ ├ 1 = 5.Int
│ │ │ ├ 2 = 6.Int
│ │ │ └ 3 = 7.Int
│ │ └ hash => {1} @5
│ │   └ dog => Newfie.Str
│ ├ one => 37.Int
│ ├ three => [5] @6
│ │ ├ 0 = 3.Int
│ │ ├ 1 = 4.Int
│ │ ├ 2 = 5.Int
│ │ ├ 3 = 6.Int
│ │ └ 4 = 7.Int
│ └ two => Buster.Str
├ dog => Nikki.Str
└ match => (1) @7
  └ 0 = 123456789[0..9|

Leave a Reply

Your email address will not be published. Required fields are marked *