Reputation: 3262
I have the following constant :
use constant => 7
is there an option to set the constant by a scalar variable once and then the value of the constant will be the initialized value i.e somthing like this :
use constant => $scalar
-> then the constant from now have the value of scalar on this point
any suggestion ?
Upvotes: 2
Views: 1047
Reputation: 107030
Constants are created at compile time by creating a subroutine that returns the value of the constant.
For example:
use constant PI => 3.1415169;
Is similar to this:
sub PI {
return 3.1415169;
}
The problem is that constants are hard to use in various situations like regular expressions or in quoted strings. There is a secret, obscure way of interpolating the constant (and this method works for other types of subroutines too. You can embed the constant inside @{[...]}
:
say "The value of pi is equal to @{[PI]}.";
# Replace value of Pi in Alabama: http://www.snopes.com/religion/pi.asp
$foo = s/@{[PI]}/3/g;
Ugly isn't it?
Another way is to use type globs:
*PI = \3.1415926;
our $PI;
This interpolates:
say "The value of pi is $PI."
But, doesn't work so well with anything other than scalars. You can define arrays and hashes, but they're not constant values.
Fortunately, there are myriads of ways to define constants that act more like variables. Unfortunately, there are myriads of ways to define constants that act more like variables and there's no standard module that comes with Perl does it. This means that you have to install some optional CPAN module on each system where you need to run your script. If these are on corporate servers, you'll probably need someone to install the module for you.
Plus, since everyone has their own favorite constant routine, you'll probably end up installing multiple modules:
The most popular one is Readonly:
use Readonly;
# For Perl 5.8 and later...
Readonly my $pi => 3.1415926;
It's fast and simple, but Readonly can be slow unless you also install Readonly:XS too, and Readonly::XS can be difficult to install if you don't have a C compiler and Make. A newer module called Const::Fast is also fairly popular:
use Const::Fast;
const my PI => 3.1415926;
say "The value of pi is $pi.";
So, there you have it.
use constant;
which is a standard module, so you know it's always available. However, it doesn't interpolate very easily. You can use the @{[...]}
syntax, but it's ugly. Upvotes: 2
Reputation: 385496
Yes, you can. Of course, you must assign the value to the scalar soon enough.
my $foo;
BEGIN {
...
...
$foo = ...;
}
use constant FOO => $foo;
You could also use do
.
use constant FOO => do {
...
...
...
};
Upvotes: 4
Reputation: 57590
Constants created with use constant
are processed at compile time, so that $scalar
variable will likely not have any value assigned yet.
You can however use the Const::Fast
module to make a scalar – well – constant:
use Const::Fast;
my $scalar = 7;
const my $constant => $scalar;
$constant = 42; # dies
This is preferable to use constant
anyway as it's nicer to handle const scalars than it is to handle constants (which are implemented as special subroutines). For example, a const scalar can be interpolated into a string.
However, compile-time constants take part in the constant folding optimization. There are some cases where this is actually necessary, so some use for use constant
remains.
(If you can't use Const::Fast
, then Readonly
is another option, although slower)
Upvotes: 7