G'day nameofmyuser,
Welcome to the Monastery.
Perl provides a number of special blocks which are executed at various points during the lifetime of the program:
"BEGIN, UNITCHECK, CHECK, INIT and END".
You can use these to check your assumptions about what's happening at these various points.
[Warning:
Do read the linked documentation, especially the begincheck example.
Some of those blocks are executed in FIFO order; and some in LIFO order.
It's not intuitively obvious which is which.]
Your assumptions appear to be correct;
although, the phrase "@test array is allocated at compile time" could be misinterpreted.
To be clear, in both of these:
my $var1;
my $var2 = 'val2';
The variables are declared at compile time; but no assignment occurs at this time.
The "$var2 = 'val2'" part of that second statement occurs at runtime.
Here's an example using some of those special blocks.
It's just a start: modify and extend as necessary.
#!/usr/bin/env perl -l
use strict;
use warnings;
my $hashref = { a => 1, b => 2 };
my @array = qw{c d e};
use constant {
HR_ARRAY => [ sort values %$hashref ],
AREF => \@array,
};
BEGIN { print join ' ', 'B1:', sort(keys %$hashref), @array }
BEGIN { print join ' ', 'B2:', @{+HR_ARRAY}, @{+AREF} }
INIT { @array = qw{f g h} }
INIT { print join ' ', 'I1:', sort(keys %$hashref), @array }
INIT { @array = qw{i j k} }
INIT { print join ' ', 'I2:', @{+HR_ARRAY}, @{+AREF} }
print join ' ', 'R1:', sort(keys %$hashref), @array;
print join ' ', 'R2:', @{+HR_ARRAY}, @{+AREF};
Output:
B1:
B2:
I1: f g h
I2: i j k
R1: a b c d e
R2: c d e
Using constant for references is generally a bad choice.
It makes the token that points to the reference a constant;
but, it does not make the values of the reference constants.
Consider these:
$ perl -E 'use constant AREF => [1..4]; say "@{+AREF}";'
1 2 3 4
$ perl -E 'use constant AREF => [1..4]; say "@{+AREF}"; AREF = []'
Can't modify constant item in scalar assignment at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
$ perl -E 'use constant AREF => [1..4]; say "@{+AREF}"; AREF->[2] = 99
+; say "@{+AREF}"'
1 2 3 4
1 2 99 4
In terms of workarounds: one of the Anonymous Monks showed a BEGIN block;
you could potentionally use an INIT block with a variation of what my code showed for AREF;
you could also just use two constants, something like this:
use constant { ONE => 1, ..., FOUR => 4 };
use constant NUM_AREF => [ ONE .. FOUR ];
[Note:
I've used NUM_AREF which could probably be improved upon; however,
HASHREFCONST is a poor, and highly misleading, choice for an arrayref constant:
it will make subsequent code difficult to understand,
and runs a high risk of being the source of coding errors.]
If you tell us how this code is intended to be used,
we can probably offer more concrete suggestions.
See also: enum — a CPAN module which you might find useful.
|