8

For example, in situations like below, I do not want to change the value of $infilename anywhere in the program after initialization.

my $infilename = "input_56_12.txt";
open my $fpin, '<', $infilename
    or die $!;

...
print "$infilename has $result matches\n";

close $fpin;

What is the correct way to make sure that any change in $infilename results in not just warnings, but errors?

Lazer
  • 90,700
  • 113
  • 281
  • 364

3 Answers3

9
use Readonly;
Readonly my $infilename => "input_56_12.txt";

Or using the newer Const::Fast module:

use Const::Fast;
const my $infilename => "input_56_12.txt";
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
8
use constant INPUT_FILE => "input_56_12.txt";

Might be what you want. If you need to initialize it to something that may change at run time then you might be out of luck, I don't know if Perl supports that.

EDIT: Oh, look at eugene y's answer, Perl does support that.

Peter C
  • 6,219
  • 1
  • 25
  • 37
  • 1
    how did you figure out from eugene's answer that Perl allows initializing to something that might change at runtime? – Lazer Nov 03 '10 at 19:03
  • @Lazer => `use` has an implicit `BEGIN` block around it making it a compile time assignment. the examples in both of eugene's answers work at runtime. to write the above at runtime `*INPUT_FILE = sub () {"input..."}; print INPUT_FILE();` which is a bit awkward and does not give you any inlining. – Eric Strom Nov 03 '10 at 19:53
  • 1
    @Lazer: His answer involved using normal variables, but using a special "Readonly" modifier (from a module) to make it illegal to change once it has been defined. – Peter C Nov 04 '10 at 03:38
4

Another popular way to create read-only scalars is to modify the symbol table entry for the variable by using a typeglob:

*infilename = \"input_56_12.txt";

This only works for global variables ("my" variables have no symbol table entry).

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 1
    @eugene: What is a *star* variable? – Lazer Nov 03 '10 at 19:07
  • 4
    That abuses an optimisation for constant subroutines added in perl 5.10.0. `sub foo () { "constant" }` will be stored as a reference to `"constant"` in the symbol table to not require a full glob for just a single value. To be portable, you'd have to do `*foo = sub () { "constant" }`, which also happens to be what the `constant` pragma does, so you might as well use that, get the optimisation, /and/ be portable. – rafl Nov 03 '10 at 19:26
  • 1
    in my opinion, this is one of the nicest ways to make a constant in Perl, faster than `Readonly`, and without the interpolation and autoquoting issues of constant subs – Eric Strom Nov 03 '10 at 19:44
  • 1
    @rafl => here the variable is in `$infilename` not `&infilename`, and seems to work fine in 5.8.8 – Eric Strom Nov 03 '10 at 19:46
  • 1
    Ooh, I accidentially read that as a symtab assignment, not a plain glob assignment. `$::{foo} = \42` is what I meant. Sorry! – rafl Nov 03 '10 at 19:54