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.
Example:
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:
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:
use constant DEV_OPS => 'dev_ops';
my $status = 'online';
say "Team ${ DEV_OPS } is ${ status }";
The above results in the following output:
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:
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:
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:
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:
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:
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.
# 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.
my @colors = qw(blue yellow orange red);
say $_ =~ COLORS_REGEXP
? "$_ is valid"
: "$_ is invalid" foreach @colors;
The above outputs:
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 function, which allows formatting of variables embedded within strings.
Thank you for reading, and the code used in this post is available on Github.
Top comments (2)
I didn't know this way to interpolate variables using this notation, also I thought it was impossible to interpolate constants, for this reason at the work we switched from
const
pragma to Readonly as suggested by the ProhibitConstantPragma perl critic policyThe important feature of constants is that they are inlined during the compile time, unlike Readonly. Interestingly,
still inlines the value, but not the reference and dereference: