I'm sure there are several ways of getting the value 'bar' to interpolate in the <> below, but what is the cleanest way, and why?
use constant FOO => 'bar';
my $msg = <<EOF;
Foo is currently <whatever goes here to expand FOO>
EOF
There are two kinds of here-docs:
<<'END'
, which behaves roughly like a single quoted string (but no escapes), and<<"END"
, also <<END
, which behaves like a double quoted string.To interpolate a value in a double quoted string use a scalar variable:
my $foo = "bar";
my $msg = "Foo is currently $foo\n";
Or use the arrayref interpolation trick
use constant FOO => "bar";
my $msg = "Foo is currently @{[ FOO ]}\n";
You could also define a template language to substitute in the correct value. This may or may not be better depending on your problem domain:
my %vars = (FOO => "bar");
my $template = <<'END';
Foo is currently %FOO%;
END
(my $msg = $template) =~ s{%(\w+)%}{$vars{$1} // die "Unknown variable $1"}eg;
The problem with a lot of the CPAN modules that do a nicer job of constants than the use constant
pragma is that they just aren't part of the standard Perl package. Unfortunately, it can be very difficult to download CPAN modules on machines you might not own.
Therefore, I've just decided to stick to use constant
until Perl starts to include something like Readonly
as part of its standard modules (and only when distros like RedHat and Solaris decide to update to those versions of Perl. I'm still stuck with 5.8.8 on our production servers.)
Fortunately, you can interpolate constants defined with use constant
if you know the arcane and mystical incantations that has been passed down from hacker to hacker.
Put @{[...]}
around the constant. This can also work with methods from classes too:
use 5.12.0;
use constant {
FOO => "This is my value of foo",
};
my $data =<<EOT;
this is my very long
value of my variable that
also happens to contain
the value of the constant
'FOO' which has the value
of @{[FOO]}
EOT
say $data;
this is my very long value of my variable that also happens to contain the value of the constant 'FOO' which has the value of This is my value of foo
say "The employee's name is @{[$employee->Name]}";
There is also another way to use constants that I used to employ before use constant
was around. It went like this:
*FOO = \"This is my value of foo";
our $FOO;
my $data =<<EOT;
this is my very long
value blah, blah, blah $FOO
EOT
say $data;
You can use $FOO
as any other scalar value, and it can't be modified. You try to modify the value and you get:
Modification of a read-only value attempted at ...
Use Const::Fast instead of Readonly
or constant
. They interpolate without any contortions. See CPAN modules for defining constants:
For conditional compilation, constant is a good choice. It's a mature module and widely used.
...
If you want array or hash constants, or immutable rich data structures, use Const::Fast. It's a close race between that and Attribute::Constant, but Const::Fast seems maturer, and has had more releases.
On the other hand, you seem to be writing your own templating code. Don't. Instead, use something simple like HTML::Template:
use HTML::Template;
use constant FOO => 'bar';
my $tmpl = HTML::Template->new(scalarref => \ <<EOF
Foo is currently <TMPL_VAR VALUE>
EOF
);
$tmpl->param(VALUE => FOO);
print $tmpl->output;
Have you considered using "read-only variables" as constants?
perlcritic recomends it at severity level 4 (default is level 5)
use Readonly;
Readonly my $FOO => 'bar';
my $msg = <<"EOF";
Foo is currently <$FOO>
EOF
P.S. Module Const::Fast
(inspired by noduleReadonly
) seems to be a better choice.
Late to the party, but another version of the arrayref trick can do this in a scalar context: ${\FOO}
. Example, tested in perl 5.22.2 on cygwin:
use constant FOO=>'bar';
print <<EOF
backslash -${\FOO}-
backslash and parens -${\(FOO)}-
EOF
produces
backslash -bar-
backslash and parens -bar-
Thanks to d-ash for introducing me to this technique, which he uses in his perlpp
source preprocessor here (see also this answer). (Disclaimer: I am now the lead maintainer of perlpp
- GitHub; CPAN.)