String Interpolation of Constants in Perl 5
Tags: perl5, interpolation, constants
Published: 2018-10-01 21:06:57

---
title: String Interpolation of Constants in Perl 5
published: true
description: Demonstration of Perl 5 constants with String Interpolation and Regular Expressions.
tags: perl5, interpolation, constants
---

This post demonstrates how to use Perl 5 constants with String Interpolation and Regular Expressions. I will briefly explain how String Interpolation works in Perl 5, especially with constants. Finally I explain how to use constants with Regular Expressions, and a use case for this.

## String Interpolation
In Perl 5, any scalar or list variables embedded within double-quotes will be substituted with their values at run-time. This type of string is known as an _Interpolated String_, and it gets resolved in a process known as [String Interpolation](https://en.wikipedia.org/wiki/String_interpolation).

_Example:_
```perl
my $PI   = 3.14;
my @nums = (3, 2, 1);

say "scalar: $PI - list: @nums";
```

The above outputs:
```
scalar: 3.14 - list: 3 2 1
```

Alternatively, Interpolated Strings in Perl 5 can contain an _identifier_ wrapped in either `${}` or `@{}`, and depending on their type, they get resolved accordingly - _in this case scalar and list respectively_

_Example:_
```perl
say "scalar: ${ PI } - list: @{ nums }";
```

outputs:
```
scalar: 3.14 - list: 3 2 1
```

In the above string, Perl looks-up and finds each identifier _i.e._ `PI` and `nums` within the current namespace, and they are resolved. 

> _Since the expressions `${}` and `@{}`  highlight the intent of Interpolation more clearly, I will use them both going forward._

However, a Constant created with the Perl 5 `constant` prama is Sigilless, as such inserting one into a double-quoted string, will not be resolved. See below:

```perl
use constant DEV_OPS => 'dev_ops';
my $status = 'online';

say "Team ${ DEV_OPS } is ${ status }";
```

The above results in the following output:

```bash
Global symbol "$DEV_OPS" requires an explicit package name...
```
The above occurred because unlike `$status`, the constant `DEV_OPS` does not have a sigil, so Perl cannot look it up and resolve it - _with regards to quotes ""_

## Resolving the Constant

To make the Interpolated String aware of any constants to be processed, a backslash `\` is used to reference it as follows:

```perl
say "Team ${ \DEV_OPS } is ${ status }";
# or if we use more than one constant
say "Team ${ \DEV_OPS } - ${ \DEV_OPS } is ${ status }";
```

Outputs:
```
Team dev_ops is online
Team dev_ops - dev_ops is online
```

### List Context
Constant values are evaluated in List context  so  `[]` can be used to reference them also. Then use the appropriate interpolation expression as follows:

```perl
say "Team @{ [DEV_OPS] }...";
```
However, I find it simpler to use backslash `\`.

---

## __Using Constants in Regular Expressions__

Lets say you have three constants, and each represents a different colour as follows:

```perl
use constant BLUE  => 'blue';
use constant GREEN => 'green';
use constant RED   => 'red';
```

Now, if you have a list of colours `@colors` which you want to validate against the three colours listed above, you may write something like this:

```perl
my  @colors = qw(blue yellow orange red);
my  $colors_regexp = qr/^(blues|green|red)$/; # typo intended...

say $_ =~ $colors_regexp
    ? "$_ is valid"
    : "$_ is invalid" foreach @colors;
```

The above outputs:
```bash
blue is invalid
yellow is invalid
orange is invalid
red is valid
```
Now `blue` in `@colors` is actually valid, but the typo `blues` in the Regular Expression, causes the match to fail. Whilst this typo is intentional, it could also happen by mistake, and be missed altogether.

__Solution__

Since each colour is defined as a Constant, it is safer to compose the Regular Expression using each one. This is done the same way I explained earlier, by using a backslash `\` to reference each constant.

```perl
# lets make the regular expression a constant also
use constant COLORS_REGEXP => qr/^(
    ${\BLUE}  |
    ${\GREEN} |
    ${\RED}
)$/x;
```

> _To make the Regular Expression easier to read, I've used the `x` option. This option allows the Regular Expression to be written on new lines, and white spaces are ignored also._

Finally lets replace the Regular Expression `$colors_regexp` with the `COLORS_REGEXP` constant.

```perl
my  @colors = qw(blue yellow orange red);

say $_ =~ COLORS_REGEXP
    ? "$_ is valid"
    : "$_ is invalid" foreach @colors;
```

The above outputs:
```bash
blue is valid
yellow is invalid
orange is invalid
red is valid
```

## Conclusion

String Interpolation using Constants in Perl 5 works the same as for scalars and lists, with the exception of using a backslash `\` to reference the them. In Perl 6 however, you can just write `say "${ constant_name }"` and that's it! Perl also has the [sprintf](https://perldoc.perl.org/functions/sprintf.html) function, which allows formatting of variables embedded within strings.

Thank you for reading, and the code used in this post is available on [Github](https://gist.github.com/kirklewis/f2b9987cb330e7b702d1e8ed46f86a22#file-perl5-string-interpolation-pl).