=head1 NAME readonly - Perl pragma to declare readonly scalars =head1 SYNOPSIS use readonly '$READONLY' => 57, '$TOPIC' => 'computing', '$TRUE' => 1, '$FALSE' => 0, '$PI' => 4 * atan2( 1, 1 ), '$ALPHA' => 1.761, '$BETA' => 2.814, '$GAMMA' => 4.012, '$PATH' => '/usr/local/lib/lout/include', '$EXE' => '/usr/local/bin/lout', ; # Have to use a separate readonly if we refer back. use readonly '$RC' => "$EXE/config", ; =head1 DESCRIPTION This pragma creates readonly scalars in the current namespace. The scalars thus created may be used in all contexts where read/write scalars would be used with the exception that you will get an C trappable run-time error "Modification of a read-only value attempted..." if you try to assign to a readonly scalar. Of course there is already a pragma, C, which provides this kind of functionality (and more, since C also handles arrays, hashes etc). However Cs must be used with different syntax in different contexts, whereas Cs can be used with the same consistent scalar syntax throughout. =head2 String Interpolation use constant PI => 4 * atan2 1, 1 ; use readonly '$PI' => 4 * atan2 1, 1 ; We can print Cs directly: print "The value of pi is $PI\n" ; But for Cs we must do this: print "The value of pi is ", PI, "\n" ; or this: print "The value of pi is @{[PI]}\n" ; =head2 Hash Keys use constant TOPIC => 'geology' ; use readonly '$TOPIC' => 'geology' ; my %topic = ( geology => 5, computing => 7, biology => 9, ) ; Using a C scalar we can simply write: my $value = $topic{$TOPIC} However, if we try to access one of the hash elements using the C: my $value = $topic{TOPIC} ; we get an unwelcome surprise: C<$value> is set to C because perl will take TOPIC to be the literal string 'TOPIC' and since no hash element has that key the result is undef. Thus in this situation we would have to write: my $value = $topic{TOPIC()} ; or perhaps: my $value = $topic{&TOPIC} ; =head2 Error Messages =over =item C Eval trappable fatal error. The reason for this pragma's existence. This will occur if you try to assign to a readonly scalar, e.g. C<$PI = 3>, or C<$PI++>. =item C Warning. The scalar name should begin with a $. (This is to allow the possibility of supporting readonly arrays and hashes in the future - if I can ever figure out how - suggestions welcome.) =item C Warning. This is why we use this pragma in the first place. If you write C 42 ;> somewhere and elsewhere write C 'benji' ;> you will get this warning. =item C value ; # Don't forget to single quote the scalar> Fatal syntax error. The name of the scalar must be in single quotes, and you must separate it from the value with either => or a comma. =item C Fatal error. Every scalar must be set to a defined scalar value. =item C Fatal error. The name being used contains "illegal" characters or begins with two leading underscores or is in this list: BEGIN INIT CHECK END DESTROY AUTOLOAD STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG =item C Warning. This will occur for example if you try to set the value to be C<'abc\'> whose last character, C<\> might be problematic. =back =head2 Do We Need It? You can achieve the same effect as: use readonly '$WEB_ADDRESS' => 'www.perlpress.com' ; by coding: use vars '$WEB_ADDRESS' ; *WEB_ADDRESS = \'www.perlpress.com' ; Similarly: use constant WEB_ADDRESS => 'www.perlpress.com' ; can be coded as: sub WEB_ADDRESS() { 'www.perlpress.com' } # No semi-colon. However, C allows us to create many readonly scalars in one go with a compact syntax: use readonly '$HOME' => '/home/summer', '$ROOT' => '/root', '$PERL' => '/usr/lib/perl', ; =head1 BUGS Only copes with scalars. Sometimes with 5.004 when using eval exception handling you get "Use of uninitialized value at..." errors; the cure is to write: eval { $@ = undef ; # rest as normal =head1 AUTHOR I copied some ideas from C. Mark Summerfield. I can be contacted as - please include the word 'readonly' in the subject line. =head1 COPYRIGHT Copyright (c) Mark Summerfield 2000. All Rights Reserved. This module may be used/distributed/modified under the same terms as perl itself. =cut