# ==================================================================
# Gossamer Threads Module Library - http://gossamer-threads.com/
#
#   constants
#   Author: Jason Rhinelander
#   CVS Info : 087,071,086,086,085      
#   $Id: constants.pm,v 1.9 2004/01/13 01:35:15 jagerman Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# ==================================================================
#
# Description:
#   Lightweight version of the standard constant.pm that allows you
#   to declare multiple scalar constants in a single compile-time
#   command. Like constant.pm, these scalar constants are optimized
#   during Perl's compilation stage.
#   Unlike constant.pm, this does not allow you to declare list
#   constants.

package constants;


use strict;
use Carp;
use vars qw($VERSION);

$VERSION = '1.00';

#=======================================================================

# Some of this stuff didn't work in version 5.003, alas.
require 5.003_96;

#=======================================================================
# import() - import symbols into user's namespace
#
# What we actually do is define a function in the caller's namespace
# which returns the value. The function we create will normally
# be inlined as a constant, thereby avoiding further sub calling 
# overhead.
#=======================================================================
sub import {
    my $class = shift;
    @_ or return; # Ignore 'use constant;'
    my %constants = @_;
    my $pkg = caller;
    {
        no strict 'refs';
        for my $name (keys %constants) {
            croak qq{Can't define "$name" as constant} .
                qq{ (name contains invalid characters or is empty)}
                unless $name =~ /^[^\W_0-9]\w*$/;
            my $scalar = $constants{$name};
            *{"${pkg}::$name"} = sub () { $scalar };
        }
    }

}

1;

__END__

=head1 NAME

constants - Perl pragma to declare multiple scalar constants at once

=head1 SYNOPSIS

    use constants BUFFER_SIZE   => 4096,
                  ONE_YEAR      => 365.2425 * 24 * 60 * 60,
                  PI            => 4 * atan2 1, 1,
                  DEBUGGING     => 0,
                  ORACLE        => 'oracle@cs.indiana.edu',
                  USERNAME      => scalar getpwuid($<);

    sub deg2rad { PI * $_[0] / 180 }

    print "This line does nothing" unless DEBUGGING;

    # references can be declared constants
    use constants CHASH         => { foo => 42 },
                  CARRAY        => [ 1,2,3,4 ],
                  CPSEUDOHASH   => [ { foo => 1}, 42 ],
                  CCODE         => sub { "bite $_[0]\n" };

    print CHASH->{foo};
    print CARRAY->[$i];
    print CPSEUDOHASH->{foo};
    print CCODE->("me");
    print CHASH->[10];                          # compile-time error

=head1 DESCRIPTION

This will declare a symbol to be a constant with the given scalar
value. This module mimics constant.pm in every way, except that it
allows multiple scalar constants to be created simultaneously. To
create constant list values you should use constant.

See L<constant> for details about how constants work.

=head1 NOTES

The value or values are evaluated in a list context, so you should
override this if needed with C<scalar> as shown above.

=head1 TECHNICAL NOTE

In the current implementation, scalar constants are actually
inlinable subroutines. As of version 5.004 of Perl, the appropriate
scalar constant is inserted directly in place of some subroutine
calls, thereby saving the overhead of a subroutine call. See
L<perlsub/"Constant Functions"> for details about how and when this
happens.

=head1 BUGS

In the current version of Perl, list constants are not inlined
and some symbols may be redefined without generating a warning.

It is not possible to have a subroutine or keyword with the same
name as a constant. This is probably a Good Thing.

Unlike constants in some languages, these cannot be overridden
on the command line or via environment variables.

You can get into trouble if you use constants in a context which
automatically quotes barewords (as is true for any subroutine call).
For example, you can't say C<$hash{CONSTANT}> because C<CONSTANT> will
be interpreted as a string.  Use C<$hash{CONSTANT()}> or
C<$hash{+CONSTANT}> to prevent the bareword quoting mechanism from
kicking in.  Similarly, since the C<=E<gt>> operator quotes a bareword
immediately to its left you have to say C<CONSTANT() =E<gt> 'value'>
instead of C<CONSTANT =E<gt> 'value'>.

=head1 AUTHOR

constant.pm: Tom Phoenix, E<lt>F<rootbeer@teleport.com>E<gt>, with help from
many other folks.

constants.pm: Jason Rhinelander, Gossamer Threads Inc.

=cut
