bikeNomad has asked for the wisdom of the Perl Monks concerning the following question:

This is something that I periodically run into, and I figured that with the amount of Perl knowledge here someone would be able to find a better way.

The problem is that I often have multiple packages/classes defined in a single file (because they're small), and frequently have to share constants between them. However, there isn't a real easy way to inherit constants and still be able to use them in their bareword form (as you can in the package in which they're defined). The best I've been able to come up with is the following; can anyone point me to a better/cleaner way to do it? I'd rather not mess with Exporter, extra BEGIN blocks, etc.

#!/usr/bin/perl -w use strict; use vars qw(@ISA @EXPORT); package A; BEGIN { require Exporter; @A::ISA = 'Exporter'; @A::EXPORT = qw(CA sa); } use constant CA => 1; sub sa { my $a = CA; # fine } package B; BEGIN { A->import(':DEFAULT'); } @B::ISA = 'A'; sub sb { my $b = CA(); # fine my $c = CA; # fine, but only after import. }
  • Comment on Inheriting constants in the same file -- help me find a better way!
  • Download Code

Replies are listed 'Best First'.
(tye)Re: Inheriting constants in the same file -- help me find a better way!
by tye (Sage) on Jun 25, 2001 at 09:02 UTC

    Well, you can skip Exporter.pm and constant.pm, since doing it yourself gives you more flexibility. For example:

    use strict; BEGIN { my %consts= ( CA => 1, AZ => 2, UT => 3, ); while( my( $name, $value )= each %consts ) { no strict 'refs'; *{$_."::".$name}= sub () { $value } for qw( A B C D ); } } package A; print CA,$/; package B; print AZ,$/; package C; print UT,$/;
    But whether that is an improvement depends on a lot things, including taste.

            - tye (but my friends call me "Tye")
Re (tilly) 1: Inheriting constants in the same file -- help me find a better way!
by tilly (Archbishop) on Jun 25, 2001 at 19:17 UTC
    Solutions:
    1. Learn to love the parens.
    2. Replace your constants with lexically scoped variables.
    3. Hack up a utility module that makes what you want easy to do.
    Here is a sample implementation of the third option:
    package Import; sub import { shift; # I don't care about my package. my $to_call = shift; my $call_from = caller; eval qq( package $call_from; # So the import goes into the right package. $to_call\->import(\@_); ); } 1;
    Call that Import.pm. And then the following little test script shows it in operation:
    package Foo; BEGIN { use base Exporter; @EXPORT = "HELLO"; @EXPORT_OK = "BYE"; } use constant HELLO => "Hello, world\n"; use constant BYE => "Goodbye, cruel world\n"; package Bar; use Import "Foo"; print HELLO; package Baz; use Import qw(Foo BYE); print BYE;
    OK, so you still have to put the definition of what you are willing to export into a BEGIN block. But that is one block, one place. If that bugs you, take a page from base and write a module that will set your @EXPORT and @EXPORT_OK for you in its import method.
Re: Inheriting constants in the same file -- help me find a better way!
by bikeNomad (Priest) on Jun 25, 2001 at 20:58 UTC