Skip to content
VLSI Mentor

Perl Part I · Module 7 · References

Dereferencing

A reference is useless until you open it. Dereferencing is that step, and Perl gives you more than one spelling for it: a braced form that always works, a bare form that works only sometimes, and an arrow that Chapter 7.4 is devoted to. Learning all three is worth it because you will read all three in other people's code. The part that actually causes bugs is not the spelling, though — it is the sigil you put in front. The sigil decides whether you are asking for the whole container, one element, or a slice, and one of the plausible-looking combinations quietly gives you a slice when you wanted an element.

Intermediate16 min readPerlPart IReferencesData Structures

Part I · Module 7 · Chapter 7.3 · Dereferencing

1. The Whole Container

Put the sigil of the thing you want in front of the reference.

Azvya Education Pvt. Ltd.VLSI Mentor
deref.pl
use strict;
use warnings;

my @marks = (72, 65, 90);
my %conf  = (retries => 3, timeout => 45);

my $aref = \@marks;
my $href = \%conf;

print "whole array, braced   : @{ $aref }\n";
print "whole array, bare     : @$aref\n";
printf "element count         : %d\n", scalar(@$aref);
printf "last index, braced    : %d\n", $#{ $aref };
printf "last index, bare      : %d\n", $#$aref;
printf "first element, braced : %d\n", ${ $aref }[0];
printf "first element, bare   : %d\n", $$aref[0];
printf "first element, arrow  : %d\n", $aref->[0];
printf "one hash value        : %d\n", ${ $href }{retries};
printf "same, arrow           : %d\n", $href->{retries};
printf "key count             : %d\n", scalar(keys %$href);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
whole array, braced   : 72 65 90
whole array, bare     : 72 65 90
element count         : 3
last index, braced    : 2
last index, bare      : 2
first element, braced : 72
first element, bare   : 72
first element, arrow  : 72
one hash value        : 3
same, arrow           : 3
key count             : 2

@{ $aref } means "the array that $aref refers to", and from there everything behaves like an ordinary array. %{ $href } does the same for a hash, which is why keys %$href works.

Note the last line prints the key count, not the keys. Chapter 6.5 established that keys returns an unpredictable order, and that does not change just because you reached the hash through a reference.

You wantWrite
the whole array@{ $aref } or @$aref
its element countscalar(@{ $aref }) or scalar(@$aref)
its last index$#{ $aref } or $#$aref
the whole hash%{ $href } or %$href
its keyskeys %{ $href } or keys %$href
one array element${ $aref }[0] or $$aref[0] or $aref->[0]
one hash value${ $href }{k} or $$href{k} or $href->{k}

2. Everything Ordinary Still Works

Once dereferenced, it is just an array. Every builtin from Modules 5 and 6 applies.

Azvya Education Pvt. Ltd.VLSI Mentor
builtins.pl
use strict;
use warnings;

my @data = (3, 1, 2);
my $r = \@data;

push @$r, 4;
print "after push    : @$r\n";
print "sorted        : ", join(" ", sort { $a <=> $b } @$r), "\n";
print "grep > 2      : ", join(" ", grep { $_ > 2 } @$r), "\n";
printf "count         : %d\n", scalar(@$r);
printf "last index    : %d\n", $#$r;
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
after push    : 3 1 2 4
sorted        : 1 2 3 4
grep > 2      : 3 4
count         : 4
last index    : 3

push, sort, grep, scalar, $# — none of them know or care that you arrived through a reference. And push @$r, 4 modified @data, for Chapter 7.2 §2's reason: there is one array.

3. The Three Element Forms Are One Thing

Azvya Education Pvt. Ltd.VLSI Mentor
three-forms.pl
use strict;
use warnings;

my @data = (10, 20, 30);
my $r = \@data;

printf "braced  \${\$r}[1] : %d\n", ${$r}[1];
printf "bare    \$\$r[1]   : %d\n", $$r[1];
printf "arrow   \$r->[1]  : %d\n", $r->[1];
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
braced  ${$r}[1] : 20
bare    $$r[1]   : 20
arrow   $r->[1]  : 20

Identical. Pick one and be consistent; the arrow is the one to pick, and Chapter 7.4 explains why it wins once structures nest. The other two matter because you will read them.

Which way does $$r[0] group?

This is worth one measurement because guessing wrong is a real source of confusion.

Azvya Education Pvt. Ltd.VLSI Mentor
group-ok.pl — written as $$r[0]
use strict;
use warnings;

my @data = (10, 20);
my $r = \@data;

printf "%d\n", $$r[0];
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
10
Azvya Education Pvt. Ltd.VLSI Mentor
group-bad.pl — written as ${$r[0]}
use strict;
use warnings;

my @data = (10, 20);
my $r = \@data;

printf "%d\n", ${$r[0]};
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — STDERR
Global symbol "@r" requires explicit package name (did you forget to declare "my @r"?) at group-bad.pl line 7.
Execution of group-bad.pl aborted due to compilation errors.

$$r[0] means ${$r}[0]. The second reading is not merely different, it refers to a different variable — ${$r[0]} subscripts @r, an array that does not exist, so it will not even compile.

The rule: the subscript applies last. The leading sigils resolve the reference first, then [0] indexes the result.

4. The Sigil Decides — Element, Slice, or Count

This is the section that prevents bugs.

Azvya Education Pvt. Ltd.VLSI Mentor
sigil-decides.pl
use strict;
use warnings;

my @data = (10, 20, 30);
my $r = \@data;

my $whole   = @$r;
my $element = $$r[0];

printf "my \$x = \@\$r    : %d   <- the COUNT\n", $whole;
printf "my \$y = \$\$r[0] : %d  <- the element\n", $element;

my @slice = @$r[0, 1];
printf "\@\$r[0,1]       : %d item(s)  [%s]\n", scalar(@slice), join(" ", @slice);
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
my $x = @$r    : 3   <- the COUNT
my $y = $$r[0] : 10  <- the element
@$r[0,1]       : 2 item(s)  [10 20]

Three different results from three sigil choices on the same reference:

  • @$r — the whole array. In scalar context that is its count, exactly as Chapter 5.7 described.
  • $$r[0] — one element.
  • @$r[0,1] — a slice, which is a list.

5. Slices Through a Reference

When you genuinely do want a list, slices work exactly as Chapter 5.3 and Chapter 6.7 describe.

Azvya Education Pvt. Ltd.VLSI Mentor
slices.pl
use strict;
use warnings;

my @data = (10, 20, 30);
my %h    = (a => 1, b => 2, c => 3);

my $r  = \@data;
my $hr = \%h;

print "array slice, braced : @{ $r }[1,2]\n";
print "array slice, bare   : @$r[1,2]\n";
print "hash slice, braced  : @{ $hr }{ qw(a c) }\n";
print "hash slice, bare    : @$hr{ qw(a c) }\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
array slice, braced : 20 30
array slice, bare   : 20 30
hash slice, braced  : 1 3
hash slice, bare    : 1 3

A hash slice through a reference is genuinely useful: @$href{qw(name width)} pulls two named fields out of a record in one expression.

6. Why the Braced Form Exists

The bare form has a real limitation, and it is not a style question.

Azvya Education Pvt. Ltd.VLSI Mentor
braces-required.pl
use strict;
use warnings;

my %r = (blocks => ["alu", "fifo"]);

print "braced : @{ $r{blocks} }\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
braced : alu fifo

Now the same thing without braces:

Azvya Education Pvt. Ltd.VLSI Mentor
braces-omitted.pl
use strict;
use warnings;

my %r = (blocks => ["alu", "fifo"]);

print "bare : @$r{blocks}\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — STDERR
Global symbol "$r" requires explicit package name (did you forget to declare "my $r"?) at braces-omitted.pl line 6.
Execution of braces-omitted.pl aborted due to compilation errors.

Read that error carefully: it is complaining about $r, a scalar that was never declared. @$r{blocks} did not parse as "dereference $r{blocks}" at all — it parsed as a hash slice of the hash referred to by a scalar $r. Completely different code.

The bare form only works when the reference sits in a simple scalar variable. Anything more complicated — a hash element, an array element, a function's return value — needs braces:

Azvya Education Pvt. Ltd.VLSI Mentor
Braces are mandatory here
@{ $r{blocks} }        # ref from a hash element
@{ $rows[3] }          # ref from an array element
@{ get_list() }        # ref from a function call
@{ $self->{items} }    # ref from a nested lookup
Azvya Education Pvt. Ltd.VLSI Mentor
braces-callret.pl
use strict;
use warnings;

sub get_list { return [1, 2, 3] }

printf "count: %d\n", scalar(@{ get_list() });
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
count: 3

That is why experienced Perl tends toward braces even in the simple case: one habit that always works beats two habits with a boundary between them. In practice most code uses the arrow for elements and braces for whole containers, which is the combination Chapter 7.4 settles on.

7. Dereferencing the Wrong Kind of Thing

Every one of these is fatal and exits 255. Nothing here warns-and-continues.

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — STDERR, one run per line
keys %$aref   ->  Not a HASH reference at -e line 1.
@$href        ->  Not an ARRAY reference at -e line 1.
@$code_ref    ->  Not an ARRAY reference at -e line 1.
$$aref        ->  Not a SCALAR reference at -e line 1.
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — STDERR, when it is not a reference at all
my $s = "hello"; @$s   ->  Can't use string ("hello") as an ARRAY ref while "strict refs" in use at -e line 1.
my $r;           @$r   ->  Can't use an undefined value as an ARRAY reference at -e line 1.

There are two message families, and the difference tells you what went wrong:

  • Not a HASH reference / Not an ARRAY reference — you had a real reference, of the wrong kind. Usually a structure that is not shaped the way you assumed: you wrote $h->{list}{name} where list holds an array reference.
  • Can't use ... — you did not have a reference. Can't use an undefined value means the thing was undef, which usually means a lookup missed; Can't use string ("hello") means a plain value arrived where a reference was expected.

8. Dereferencing Inside Strings

All the forms interpolate, which is worth knowing because it keeps report code readable.

Azvya Education Pvt. Ltd.VLSI Mentor
interpolation.pl
use strict;
use warnings;

my @data = (10, 20);
my %h    = (a => 1);

my $r  = \@data;
my $hr = \%h;

print "bare array   : @$r\n";
print "braced array : @{ $r }\n";
print "element bare : $$r[0]\n";
print "element arrow: $r->[0]\n";
print "hash arrow   : $hr->{a}\n";
print "hash braced  : ${ $hr }{a}\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
bare array   : 10 20
braced array : 10 20
element bare : 10
element arrow: 10
hash arrow   : 1
hash braced  : 1

The array forms join with a space, following Chapter 4.2's rule for array interpolation. The arrow works inside strings too, which is not true in every language with arrow syntax and is genuinely convenient.

9. Why This Matters in Engineering Work

Reading a nested structure is dereferencing, repeatedly. $report->{blocks}{alu}{slack} is three dereferences. Everything in Chapters 7.6 through 7.10 is this chapter applied several times in a row.

The two error families are a fast diagnostic. When a script dies on a netlist or report that is shaped slightly differently from the one you developed against, the message tells you which half of the problem you have: Not an ARRAY reference means your assumption about the structure's shape was wrong, Can't use an undefined value means a lookup returned nothing. Those lead to different fixes, and distinguishing them without a debugger is worth the thirty seconds it takes to learn the wording.

And the sigil discipline is what keeps the code honest. In a loop over ten thousand timing paths, @$r[0] instead of $$r[0] will not announce itself. Leading with $ for one value and @ for a list — or just using the arrow — removes the whole class.

10. Common Mistakes

@$r[0] when you meant $$r[0]. That is a one-element slice. It returns the right value and does not warn, so it survives until the shape matters.

my $n = @$r expecting an element. That is the count.

Omitting braces when the reference is not a simple scalar. @$r{blocks} is a hash slice, and the error names a variable you never wrote.

Reading ${$r[0]} as $$r[0]. Different variable; it needs @r.

Hash-dereferencing an array reference. Not a HASH reference, fatal.

Chasing a Can't use an undefined value into the dereference. Look at the key on the line before.

Assuming keys %$href has an order. It does not, through a reference or otherwise.

11. Exercise

Exercise 1 — the whole container. Take references to a three-element array and a two-key hash. Print the whole array both braced and bare, its count, its last index, and the hash's key count. Do not print the keys themselves, and say in one sentence why not.

Exercise 2 — builtins through a reference. Through an array reference only, push a value, print the array sorted numerically, and print the elements greater than 2. Then confirm the original named array changed.

Exercise 3 — three spellings. Print element 1 using the braced, bare and arrow forms. Confirm all three agree, then state which you intend to use for the rest of the module.

Exercise 4 — the grouping proof. Print $$r[0] successfully. Then write ${$r[0]} and record the compile error. Explain in one sentence which variable the second form was looking for.

Exercise 5 — the sigil trap. On a three-element array reference, print my $x = @$r, $$r[0], and the length of my @y = @$r[0]. Then do the same with @$r[0,1]. Say which of these you would never write deliberately.

Exercise 6 — braces required. Build my %r = (blocks => ["alu","fifo"]);. Print the inner list with braces. Then try it without braces, record the exact error, and explain why the error names $r.

Exercise 7 — both error families. Produce all four of: Not a HASH reference, Not an ARRAY reference, Can't use an undefined value as an ARRAY reference, and Can't use string (...) as an ARRAY ref. Record each message and exit status, then write one sentence per family saying what it tells you to go and look at.

Exercise 8 — the key typo that says nothing. Build a hash reference with a key blocks holding a two-element array reference, then loop over @{ $conf->{block} } — singular. Record STDOUT, STDERR and the exit status. Then check whether block exists in the hash afterwards. Finally, put the same misspelled lookup in my @x = @{ $conf->{block} }; and record what changes. Write one sentence on which of the two you would rather ship.

12. Summary

  • Put the sigil of what you want in front of the reference: @$aref, %$href, $#$aref, keys %$href.
  • Once dereferenced it is an ordinary container — push, sort, grep, scalar all work unchanged, and they modify the original.
  • ${$r}[1], $$r[1] and $r->[1] are the same element. The arrow is the one to adopt.
  • $$r[0] means ${$r}[0] — the subscript applies last. ${$r[0]} is a different variable.
  • The sigil decides the shape: @$r is the whole array (a count in scalar context), $$r[0] is an element, and @$r[0] is a one-element slice that never warns.
  • The bare form only works when the reference is in a simple scalar. A hash element, array element or function result needs @{ ... }.
  • Wrong-kind dereference is fatal, and there are two families: Not a HASH reference when it is a reference of the wrong kind, Can't use ... when it is not a reference at all.
  • Can't use an undefined value is usually a misspelled key, not a reference problem.

Chapter 7.4 takes the arrow seriously: why it exists, where it is optional, and the one place it absolutely is not.

Where this fits

Part of the Perl curriculum.