NAME

readonly - Perl pragma and function module to create readonly scalars

SYNOPSIS

##### Compile time -- create, assign & set readonly in one step

use readonly 
        '$MAX_LINES' => 70,
        '$TOPIC'     => 'computing',
        '$TRUE'      => 1,
        '$FALSE'     => 0,
        '$PI'        => 4 * atan2( 1, 1 ),

        '$ALPHA'     => 1.761,
        '$BETA'      => 2.814,
        '$GAMMA'     => 4.012,
        '$PATH'      => '/usr/local/lib/project/include',
        '$EXE'       => '/usr/local/bin/project',
        ;

# Have to use a separate readonly if we refer back.
use readonly '$RC'  => "$EXE/config" ;

$RC = '/new/path' ; # eval trappable error

##### Run time -- set readonly

use readonly () ; # If no previous pragma calls.

use vars qw( $BACKGROUND $FOREGROUND $HIGHLIGHT ) ; # Predeclare.

$BACKGROUND = param( 'green' ) ;    # Pre-assign
$FOREGROUND = param( 'blue' ) ;
$HIGHLIGHT  = param( 'yellow' ) ;

readonly->set( '$BACKGROUND', '$FOREGROUND', '$HIGHLIGHT' ) ;

$BACKGROUND = 'red' ; # eval trappable error

DESCRIPTION

The readonly module can be used either as a compile-time pragma or a run-time class module.

When used as a pragma it creates readonly scalars in the current namespace. When used as a function module it marks scalars as readonly. Only package scalars may be made readonly, not my scalars. readonly scalars may be used in all contexts where read/write scalars would be used with the exception that you will get an eval trappable run-time error "Modification of a read-only value attempted..." if you try to assign to a readonly scalar.

The pragma, constant, provides apparently similar functionality (and more, since constant also handles arrays, hashes etc). However constants are not readonly scalars, but rather subroutines which behave like them and which must be used with different syntaxes in different contexts. readonlys can be used with the same consistent scalar syntax throughout. Also readonlys may be set either at compile-time or at run-time.

String Interpolation

use readonly '$PI' => 4 * atan2 1, 1 ; # Compile time
use constant PI    => 4 * atan2 1, 1 ; # Compile time

We can print readonlys directly:

print "The value of pi is $PI\n" ;

but for constants we must do this:

print "The value of pi is ", PI, "\n" ;

or this:

print "The value of pi is @{[PI]}\n" ;

Hash Keys

use readonly '$TOPIC' => 'geology' ;
use constant TOPIC    => 'geology' ;

my %topic = (
        geology   => 5,
        computing => 7,
        biology   => 9,
    ) ;

Using a readonly scalar we can simply write:

my $value = $topic{$TOPIC}

however, if we try to access one of the hash elements using the constant:

my $value = $topic{TOPIC} ;

we get an unwelcome surprise: $value is set to undef 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} ;

Runtime readonly's

Sometimes we only know what the readonly value will be after performing some of our execution; in such cases we can use readonly->set to make an existing scalar readonly:

use readonly () ; # If not already use'd
use vars qw( $RED $GREEN $BLUE $YELLOW ) ; # Predeclare

$RED    = '#FF0000' ; # Pre-assign
$GREEN  = '#00FF00' ;
$BLUE   = '#0000FF' ;
$YELLOW = '#FFFF00' ;

readonly->set( '$RED', '$GREEN', '$BLUE', '$YELLOW' ) ;

BUGS

Only copes with scalars.

In some tests with 5.004 readonly->set gives spurious warnings.

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

AUTHOR

Mark Summerfield. I can be contacted as <summer@perlpress.com> - please include the word 'readonly' in the subject line.

I copied some ideas from constant.pm.

COPYRIGHT

Copyright (c) Mark Summerfield 2000. All Rights Reserved.

This module may be used/distributed/modified under the same terms as perl itself.

SEE ALSO

Constant or readonly scalars, arrays and hashes are available through other mechanisms:

  • Tom Phoenix's standard module constant. This has the cons described above, but the pros that it can provide readonly arrays and may be faster than other approaches because the perl compiler cooperates with it behind the scenes.

  • Graham Barr's tie-based code archived at http://www.xray.mpe.mpg.de/mailing-lists/modules/1999-02/msg00090.html

  • Mark-Jason Dominus' tie-based code at http://www.plover.com/~mjd/perl/Locked/

  • My own tie-based code at http://www.perlpress.com/perl/antiques.html Tie::Const.

Tie-based implementations should be able to offer readonly scalars, arrays and hashes, but these implementations are likely to have a performance overhead compared with readonly or constant.