Skip to content
VLSI Mentor

Perl Part I · Module 7 · References

Inspecting a Structure With Data::Dumper

When a nested structure does not contain what you expected, the fastest way to find out what it does contain is to print the whole thing. Data::Dumper does that in two lines, it ships with Perl so there is nothing to install, and it handles any shape and any depth. The default output is correct but awkward to read and — more importantly — not reproducible between runs, because it inherits the hash key ordering that Chapter 6.5 established is unpredictable. Three settings fix all of that. This chapter covers what the output actually looks like, which settings are worth making habitual, and where Data::Dumper is the wrong tool despite being tempting.

Intermediate15 min readPerlPart IReferencesDebugging

Part I · Module 7 · Chapter 7.12 · Inspecting a Structure With Data::Dumper

1. Two Lines

Azvya Education Pvt. Ltd.VLSI Mentor
dd-default.pl
use strict;
use warnings;
use Data::Dumper;

my $design = {
    blocks => ["alu", "fifo"],
};

print Dumper($design);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
$VAR1 = {
          'blocks' => [
                        'alu',
                        'fifo'
                      ]
        };

Data::Dumper is part of core Perl — version 2.179 on the 5.34.1 used throughout this module — so use Data::Dumper; needs no installation anywhere Perl runs.

This example has one key per level on purpose. Add a second key alongside blocks and the dump stops being reproducible: five runs of that version produced two different key orders, because no Sortkeys is set yet. The format — the $VAR1 =, the indentation, the quoting — is stable either way, and §2 is about fixing the order.

That output is complete and correct. It is also doing three things you will usually want to change:

  • $VAR1 = and the trailing semicolon. The default output is valid Perl source, which matters for the round-trip use in §4 and is noise when you are just looking.
  • Indentation that tracks the key width. 'blocks' => [ pushes its contents out to align under the bracket, so the indentation of a value depends on the length of the key above it. Deep structures drift far to the right.
  • No key ordering. With one key per level there is nothing to order; §2 shows what happens with two.

2. Three Settings Worth Making Habitual

Azvya Education Pvt. Ltd.VLSI Mentor
dd-tuned.pl
use strict;
use warnings;
use Data::Dumper;

$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent   = 1;
$Data::Dumper::Terse    = 1;

my $design = {
    blocks => ["alu", "fifo"],
    limits => { retries => 3, timeout => 45 },
};

print Dumper($design);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
{
  'blocks' => [
    'alu',
    'fifo'
  ],
  'limits' => {
    'retries' => 3,
    'timeout' => 45
  }
}

Compare that with §1. Same kind of data, far easier to read.

SettingEffect
$Data::Dumper::Sortkeys = 1hash keys come out in sorted order, every run
$Data::Dumper::Indent = 1fixed two-space indent per level instead of key-width alignment
$Data::Dumper::Terse = 1drops $VAR1 = and the trailing semicolon

Indent also accepts 0 and 2. Measured on the same data:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — Indent = 0
$VAR1 = {'blocks' => ['alu','fifo'],'limits' => {'retries' => 3}};

Everything on one line, which is what you want for logging a small structure as a single record.

Indent = 2 is the default from §1 — the same nine lines as Indent = 1, but each level indented to align under the key above it rather than by a fixed two spaces:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — Indent = 2, leading spaces shown as dots
$VAR1 = {
..........'blocks' => [
........................'alu',
........................'fifo'
......................],
..........'limits' => {
........................'retries' => 3
......................}
........};

Twenty-four columns of indent at two levels deep, against four for Indent = 1. That is the drift mentioned in §1, and it is why Indent = 1 is the setting to prefer.

3. Dumping Several Things, and Naming Them

Dumper takes any number of arguments and numbers them $VAR1, $VAR2 and so on — which is why Terse is off by default.

Azvya Education Pvt. Ltd.VLSI Mentor
dd-many.pl
use strict;
use warnings;
use Data::Dumper;

$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent   = 1;

my $aref = [1, 2];
my $href = { k => "v" };

print Dumper($aref, $href);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
$VAR1 = [
  1,
  2
];
$VAR2 = {
  'k' => 'v'
};

When you are dumping several structures, names are more useful than numbers. Data::Dumper->Dump takes a list of values and a list of names:

Azvya Education Pvt. Ltd.VLSI Mentor
dd-named.pl
use strict;
use warnings;
use Data::Dumper;

$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent   = 1;

my $before = { slack => -0.12 };
my $after  = { slack =>  0.05 };

print Data::Dumper->Dump([$before, $after], ['before', 'after']);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
$before = {
  'slack' => '-0.12'
};
$after = {
  'slack' => '0.05'
};

For debugging two versions of the same structure — before and after a transformation, expected and actual — named output saves you counting $VAR numbers.

Note the numbers came out quoted as '-0.12' and '0.05'. That is not because they had been used as strings — a freshly written numeric literal dumps the same way. The rule is narrower, and measured:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — what Dumper quotes
int 3        : 3
int -7       : -7
float 0.5    : '0.5'
float -0.12  : '-0.12'
string abc   : 'abc'
string 3     : '3'
1e10         : '10000000000'

Integers come out bare; floating-point values come out quoted, alongside actual strings. The quoting therefore tells you something about Perl's internal representation and nothing about whether you treated the value as text — and note the last line, where 1e10 was also expanded as well as quoted.

The practical consequence is in §4: the output is for reading, not for comparing values. '0.5' and 0.5 are the same number and different text.

4. Where It Is the Wrong Tool

Do not use it to move data between programs. Because the default output is valid Perl, it is tempting to write a dump to a file and read it back with eval. That works and you should not do it: eval on a file's contents executes whatever is in that file, so a corrupted or hostile dump becomes code execution in your script. For data that has to persist or travel, use a format meant for it — JSON::PP is core and is the usual answer.

Do not use it to compare structures. The temptation is Dumper($a) eq Dumper($b). With Sortkeys set it is more reliable than you might expect, but it still compares representations — the '-0.12' quoting above is an example of two structures with the same numeric content that could dump differently. Compare the data.

Do not use it on huge structures without thought. A dump of a hundred-thousand-leaf structure is a very large amount of text, produced slowly. Dump a slice instead: Dumper($report->{$one_block}).

And do not leave it in production code. print Dumper(...) left behind is the Perl equivalent of a stray debug print, except it can emit megabytes. Chapter 7.10's walker is the better choice when the inspection is a permanent feature, because you control exactly what it emits.

5. Dumper or a Walker?

Both tools inspect structures and they are not interchangeable.

Use Data::Dumper whenUse a walker (Chapter 7.10) when
you want to see the whole shape nowyou need to do something per node
you are debugging interactivelythe inspection ships as a feature
the structure is small enough to readyou want one line per leaf, with paths
you want it in two linesyou want to filter, count or validate

The practical division: Dumper for a question you are asking once, a walker for a question your program asks every run. A walker's path output — design{blocks}[7]{ports}[2] — is also easier to act on than a braces-and-indentation tree when you are hunting one bad value in a large structure.

6. Why This Matters in Engineering Work

It is the fastest answer to "what did I actually build?" Most bugs in nested-data code are shape bugs — a level deeper than you thought, a value that is a reference when you expected a string, a key that autovivified. One Dumper call shows all three immediately.

Sortkeys is what makes a dump a record. Saving a dump of a parsed report, re-running after a change, and diffing is a genuinely good debugging technique, and it does not work at all without stable ordering.

And knowing its limits saves a bad decision. The eval-a-dump round trip is a real pattern in old Perl scripts and a real problem. Reaching for JSON::PP instead costs nothing and is core.

7. Common Mistakes

Not setting Sortkeys. The output order varies between runs and cannot be diffed.

Leaving Terse off when reading. $VAR1 = and the semicolon are noise unless you need valid Perl.

Leaving Indent at the default. Indentation tracks key width, so deep structures drift right.

eval-ing a dump to load data. That executes the file. Use JSON::PP.

Comparing structures with Dumper($a) eq Dumper($b). It compares representations, and numbers may be quoted.

Dumping a huge structure. Dump a slice.

Leaving print Dumper(...) in shipped code. Use a walker if the inspection is permanent.

8. Exercise

Exercise 1 — the default. Build a two-key structure where one value is an array reference and the other a hash reference. Print it with Dumper and no settings. Note the $VAR1, the semicolon, and how far right the nested values sit.

Exercise 2 — tuned. Add Sortkeys, Indent = 1 and Terse = 1. Print it again and compare. State which setting removed which piece of noise.

Exercise 3 — Indent variants. Print the same structure with Indent set to 0, 1 and 2. Record the line count of each — note that two of them match — and then measure the leading-space count on the deepest line of each. Say which you would use in a log file and which for reading on a terminal.

Exercise 4 — five runs. Build a hash with at least five keys and set Indent = 0 so each dump is one line. Dump it without Sortkeys five times, pipe the runs through sort -u, and count the distinct outputs. Then do the same with Sortkeys. Report both counts and say what that means for saving a dump as a record.

Exercise 5 — several at once. Dump two structures in one Dumper call and note the $VAR1/$VAR2 naming. Then use Data::Dumper->Dump with the names before and after and compare the readability.

Exercise 6 — what gets quoted. Dump each of these separately with Terse = 1 and Indent = 0: the integer 3, the integer -7, the float 0.5, the float -0.12, the string "abc", the string "3", and 1e10. Record which came out quoted. State the rule in one sentence, and say why it means you should not compare two structures by comparing their dumps.

Exercise 7 — a slice. Build a structure with three blocks and dump only one of them. Compare the output size with dumping the whole thing.

Exercise 8 — Dumper or walker. Take Chapter 7.10's walker and run it on the same structure you dumped in Exercise 2. Put both outputs side by side and write two sentences on which you would rather have for finding one wrong value among many.

9. Summary

  • use Data::Dumper; print Dumper($ref); prints any structure in two lines. It is core — version 2.179 here — so there is nothing to install.
  • Set $Data::Dumper::Sortkeys = 1. Measured on a five-key hash: five distinct outputs from five runs without it, one with it. Without it the output cannot be diffed.
  • $Data::Dumper::Indent = 1 gives a fixed two-space indent instead of key-width alignment; 0 puts it on one line.
  • $Data::Dumper::Terse = 1 drops $VAR1 = and the trailing semicolon.
  • Dumper takes several arguments and numbers them; Data::Dumper->Dump([...], ['name', ...]) names them instead.
  • Integers dump bare and floating-point values dump quoted, alongside strings. That is a representation hint, not a problem — and a reason not to compare dumps.
  • Do not eval a dump to load data. That executes the file; use JSON::PP, which is also core.
  • Do not compare structures by comparing their dumps, and dump a slice rather than a huge structure.
  • Dumper for a question asked once; a walker for one your program asks every run.

Chapter 7.13 returns to building, with the question this module has deferred twice: when you copy a nested structure, what is actually copied and what is still shared.

Where this fits

Part of the Perl curriculum.