Interpolation#

Double-quoted strings, here-docs, regex patterns, the s/.../.../ replacement, and qq// all interpolate: they expand variables and certain escape sequences in place. Single-quoted strings, q//, and the LHS pattern of tr/.../.../ do not. Knowing which constructs interpolate and exactly which forms get expanded is one of the most useful pieces of Perl knowledge.

my $name = "Alice";
my @nums = (1, 2, 3);

"hello, $name"              # "hello, Alice"
'hello, $name'              # 'hello, $name' — single quotes don't interpolate
"@nums in a string"         # "1 2 3 in a string"
"\$name is $name"           # "$name is Alice"

What interpolates#

Inside "" (and the other double-quotish contexts), Perl expands exactly two shapes of variable:

$name              # scalar — the simple form
@list              # array  — joined by $" (one space by default)

Plus the bracket-and-brace subscript forms that compose on top of those:

$arr[0]            # one element of @arr
$h{key}            # one value from %h
$ref->[0]          # via array ref
$ref->{key}        # via hash ref
@arr[1, 2]         # array slice
@h{qw(a b)}        # hash slice

Note that whole hashes do not interpolate:

"hash is %h"       # "hash is %h" — literal '%' is fine, '%h' is NOT magical

If you want a hash dumped into a string, format it explicitly with Data::Dumper or a manual join.

What does not interpolate#

&sub               # function calls don't interpolate
sub_with_args($x)  # neither do calls with arguments
$h->method         # method calls don't interpolate
$obj->{a} + 1      # arithmetic doesn't interpolate
$arr[0+1]          # this DOES interpolate as $arr[0+1] — subscripts allow expressions

"\u\L$name"        # case-modifying escapes — these DO interpolate
"\x{2603}"         # numeric escapes — DO interpolate (a snowman)

The rule of thumb: variables and their subscripts interpolate; function/method calls and arithmetic on top of them do not. When you want an expression interpolated, see the @{[ ... ]} and ${\ ... } constructs below.

The ${name} braces#

Curly braces around a variable name disambiguate where the name ends:

my $who = "Larry";

"${who}speak"          # "Larryspeak"
"$whospeak"             # "" with warning: $whospeak is uninitialised
"${who}::sub"           # "Larry::sub"
"$who::sub"             # the variable $who::sub from package who — bug

Without the braces, Perl is greedy: $whospeak reads as one identifier, $who::sub reads as a package-qualified name. The braces force the parser to stop at }.

This is not the same brace-form as a hash subscript:

"$h{key}"              # hash element                 — what most people mean
"${h}{key}"            # hash element in a different parse path — same result
"${h{key}}"            # also the same
"${\(\$h{key})}"        # the absurd "interpolate an expression" form

The ${name} braces are mostly used for the disambiguation case (name followed by alphanumerics that would otherwise be eaten), not for hash access.

The @{...} and ${...} deref-with-braces forms#

When you want to dereference something inside a string, the brace form lets the deref expression be arbitrary:

my $config = { users => ['Alice', 'Bob'] };

"users: @{ $config->{users} }"     # "users: Alice Bob"
"users: $config->{users}"          # "users: ARRAY(0x...)" — wrong; whole arrayref stringified
"users: @$config->{users}"         # parse error / wrong

The @{ EXPR } form deref’s EXPR as an array. The braces are required because the deref target is an expression, not a plain variable. @$config->{users} doesn’t parse the way intended — @$config would deref $config as an array, and ->{users} is a hash-element access on what’s left.

The same for ${ EXPR } (scalar deref) and %{ EXPR } (the hash deref, which returns a flat list, rarely useful in interpolation).

@{[ expr ]} — interpolate any list expression#

To interpolate the result of an arbitrary expression, wrap it in @{[ ... ]}:

my $name = "World";
print "hello, @{[ uc $name ]}!\n";              # "hello, WORLD!"

print "found @{[ scalar @hits ]} matches\n";     # interpolate a count

print "users: @{[ join ', ', @users ]}\n";       # interpolate a join

The mechanism: [ ... ] builds an anonymous array reference whose contents are the expression’s list-context value; @{ ... } then deref’s that arrayref back into a list, which interpolates as a list does (joined by $").

This is the canonical workaround for «I want a function call inside a double-quoted string». The alternative is concatenation:

print "hello, " . uc($name) . "!\n";             # equivalent

The @{[ ... ]} form is denser when there are multiple interpolations; concatenation is clearer when there’s just one. In templates with many fields, printf or sprintf is usually clearer still:

printf "found %d matches\n", scalar @hits;

Use @{[ ... ]} when you genuinely want a Perl expression in the middle of a string and the alternatives are uglier.

${\ expr } — interpolate a scalar expression#

The scalar counterpart of @{[ ... ]}:

print "answer: ${\ 6 * 7 }\n";                   # "answer: 42"
print "ts: ${\ scalar localtime }\n";             # "ts: Mon Apr 27 ..."

\ EXPR makes a reference to the scalar value of EXPR; ${ ... } deref’s it. The result is one value, interpolated as a scalar.

For most cases the @{[ ... ]} form is more uniform — it works for both scalar and list contexts. ${\ ... } is occasionally clearer when you specifically want scalar context:

"got @{[ items() ]} items"      # items() called in LIST context
"got ${\ items() } items"        # items() called in SCALAR context

Hash-subscript ambiguity in patterns#

Inside a regex pattern (which is double-quotish), the parser has to guess whether $foo[bar] means «interpolate $foo[bar] (one element of @foo)» or «interpolate $foo and then match a character class [bar]»:

my @foo = ('hi');
$x =~ /$foo[abc]/                 # @foo exists — parsed as $foo[abc] (one element)
$x =~ /$foo[abc]/                 # @foo doesn't exist — parsed as $foo + char class

The disambiguation is the brace form:

$x =~ /${foo}[abc]/               # $foo + character class [abc]
$x =~ /$foo[5]/                   # element 5 of @foo
$x =~ /\Q$foo\E[abc]/             # $foo (literal) + character class

The \Q...\E quoter disables metacharacter interpretation inside its scope, which is the cleanest fix when the variable is a user input.

Heredocs#

Heredocs are double-quotish unless the marker is single-quoted:

my $msg = <<EOM;
Hello, $name!
The hash is %h.
EOM
# "Hello, Alice!\nThe hash is %h.\n" — $name interpolated, %h literal

my $msg = <<'EOM';
Hello, $name!
EOM
# "Hello, $name!\n" — single-quoted marker disables interpolation

Indented heredocs (Perl 5.26+) ignore leading whitespace up to the shortest run on any line:

my $msg = <<~EOM;
    Hello, $name!
    EOM
# "Hello, Alice!\n" — leading "    " stripped from every line

The ~ form is preferred in modern code; the un-indented form is ugly inside loops and method bodies.

Real example: building HTML safely#

my @items = ('Apples', 'Bananas', 'Cherries');

my $html = <<~HTML;
    <ul>
    @{[ map { "  <li>$_</li>" } @items ]}
    </ul>
    HTML

The map returns a list of <li>...</li> strings; @{[ ... ]} interpolates them; the implicit $" is a single space, giving:

<ul>
  <li>Apples</li>   <li>Bananas</li>   <li>Cherries</li>
</ul>

To get newlines between the items, set $" locally:

my $html = do {
    local $" = "\n";
    <<~HTML;
        <ul>
        @{[ map { "  <li>$_</li>" } @items ]}
        </ul>
        HTML
};

Or join explicitly:

my $li = join "\n", map { "  <li>$_</li>" } @items;
my $html = "<ul>\n$li\n</ul>\n";

The explicit join is usually clearer for non-trivial templates. The @{[ ... ]} form earns its place when the template is mostly literal text with one or two embedded computations.

What the special variable $" controls#

The list separator in interpolation:

my @x = (1, 2, 3);
print "x = @x\n";                         # "x = 1 2 3" — default $" is " "

local $" = ", ";
print "x = @x\n";                         # "x = 1, 2, 3"

local $" = "\n  ";
print "items:\n  @x\n";                   # "items:\n  1\n  2\n  3"

$" is the canonical way to control how arrays interpolate without rewriting the string. See filehandle and printing state for the family of separator variables.

See also#

  • Scalars, Arrays, Hashes — the shapes that interpolation expands.

  • References — the @{ EXPR } deref form and what the \ in ${\ ... } does.

  • $" — the list separator for array interpolation.

  • $,, $\, $/ — the related separator variables for print and input.

  • sprintf, printf — the explicit format-string alternative when the template is mostly punctuation.

  • qq, q, qw — the quote-like operators with custom delimiters.