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

Hello,

Question: Can the use of "use" be considered same as the include file functionality?

Goal: The Goal at higher level is to define all constants in one place. These can then be used by all of the modules that share these constants. However I don't want to have to explicitly classify each use of the constant with $PkgName:: classifier from each of the calling module.

Approach 1
If I have a file MyConstants.pm which has only "use constants ..." type statements, no other statements not even package <PkgName>; then can I still do

use MyConstants;

to get all the constants in the callers nampespace?

Approach 2)
Probably the better way of doing this is to define MyConstants as a package and export all the symbols out so that the caller would automatically import them when they do "use MyConstants ;" .

Looking for some advice.

Best Regards.

Replies are listed 'Best First'.
Re: Is "use" same as include?
by ikegami (Patriarch) on Jul 15, 2009 at 18:31 UTC

    Question: Can the use of "use" be considered same as the include file functionality?

    No. require doesn't inline the file like C's #include, and loading a file without a package using require is wrong. It definitely won't work here. (use is implemented in terms of require.)

    do might do the trick, but why not just use Exporter?

    package MyConstants; use strict; use warnings; use Exporter qw( import ); use constant qw( ); my %constants = ( FOO => 1, BAR => 2, ); our @EXPORT = keys(%constants); our %EXPORT_TAGS = ( all => [ keys(%constants) ] ); constant->import(\%constants); 1;
    or
    package MyConstants; use strict; use warnings; use Exporter qw( import ); my %constants; BEGIN { %constants = ( FOO => 1, BAR => 2, ); } use constant \%constants; our @EXPORT = keys(%constants); our %EXPORT_TAGS = ( all => [ keys(%constants) ] ); 1;
Re: Is "use" same as include?
by Marshall (Canon) on Jul 15, 2009 at 19:21 UTC
    I've seen this question before. I'm going to give the same answer (3) None of the above...use a simple DB like a .INI file for this if there a bunch of them. As I said before, you can make a very thin layer for the MyConstants.pm module.

    Having said that, alarm bells go off in my brain as to how many of these constants do you have? 10,50,100?

    The reason that I'm asking is that in C, a lot of of these #define things have to do with a) memory limits (like array bounds..MAX_LINE_BYTES, etc) or b) stuff like thing "3" in this array means "name". Using Perl constants for either a or b is not the right Perl way.

    So anyway, say you have a dozen of these things....the below code will do it. The code in your modules would look like use MyConstants(VAR1 VAR3); I LOVE C, but this is not C. You don't have to import any variable into your name space that you don't need. In C there will be hundreds if not thousands of vars imported into your compile name space via the .h files! In Perl, you can specify which vars you want to import, below this is specified by @EXPORT_OK. If you want all of them, then put them in the @EXPORT list (the default export/import list). Also, in Perl there is really no such thing as a truly "private variable". Even if VAR3 is not exported, it can still be accessed via $MyConstants::VAR3, assuming that $VAR3 has package scope which is what "our" does.

    Anyway the below scheme should work fine for like a dozen vars.

    #file MyConstants.pm use strict; use warnings; package MyConstants; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); use Exporter; our $VERSION=0.1; our @ISA = qw(Exporter); our @EXPORT = qw(); #default export our @EXPORT_OK = qw(VAR1 VAR2 VAR3); #by request export our $VAR1 ="something"; our $VAR2 ="something_else"; our $VAR3 ="something_way_else"; 1;
    Update:
    I just read the ikegami post and it is completely correct as usual! Perl is not a "lightweight" language. I tried in my code to do something similar to what you would expect with a C .h file. I did not worry about whether some var is truly "constant" or not. I assume that you won't give these vars names or use them in a way that you wouldn't in a C program. Anyway "use MyConstants(VAR1); is most assuredly NOT the same as #include MyConstants.h
      Thank you folks.

      To answer some question in reply
      a) I have about 500 some constants
      b) Yes the plan was to use these constants for "stuff like thing "3" in this array means "name".
      This is not the right approach for that?
      c) Yes I am currently using the Exporter for this. Here is the code (The recipe to export all symbols is a modified version of a reply that I came across in a different post here at perlmonk)
      package MyConstants; require Exporter; @ISA = qw(Exporter); our @EXPORT = do { no strict 'refs'; keys %{ __PACKAGE__ . '::'}; }; use constant VAR1 => VAL1; use constant VAR2 => VAL2; #--- 500 more of these 1;
      Each of the other modules module1.pm, module2.pm, module3.pm then have
      use MyConstants;
        If you intend to export 500 things, then I would argue that there is something fundamentally wrong with the design.

        As what I would call a "sanity check", go look at some HUGE Perl modules. Some of these things have mind-bending, brain-twisting, byzantine complexity, but NONE that I've found have a module that exports 500 things! A dozen? Yeah! Some dozens or even a hundred, maybe! But 500? No!

        Perl has amazing abilities to deal with arrays and complex structures without the use of indicies, without needing a #define statement. Say:

        @stuff = my($low_temp, $high_temp, $average_temp = split(/\s+/,$line); + $stuff[0] is $low_temp. Do I need a #define LOW_TEMP 0\ /*low_temp var*/$stuff[LOW_TEMP]? NO! I just use the variable name that has just been declared: $low_temp. Forget the idea of $stuff[0] or $stuff[LOW_TEMP].

        If you could make a short example of why you need so many global variables, it would be helpful because I don't know how to help you further with the data that I have so far.

        That exports too much. You can't unconditionally export everything that's in the package! Once you fix it, you end up with the code I posted earlier in this thread.
Re: Is "use" same as include?
by shmem (Chancellor) on Jul 16, 2009 at 09:16 UTC

    Warning: Don't use the following *as is*, you might get beaten. But for the sake of TIMTOWTDY...
    See note at the end.

    I concur with Marshall, that having 500 symbols to export smells like a design flaw. But that must not be the case. You could use perl's subroutine of last resort - AUTOLOAD - and not export anything explicitly...

    package MyConstants; use strict; our $AUTOLOAD; sub import { my $package = shift; if ($_[0] eq 'AUTOLOAD') { my $caller = caller; no strict 'refs'; *{$caller.'::AUTOLOAD'} = \&{$package.'::AUTOLOAD'}; } } # Constants use constant { NIL => 0, FOO => 1, BAR => 2, }; sub AUTOLOAD { (my $func = $AUTOLOAD) =~ s/.*:://; no strict 'refs'; *{$AUTOLOAD} = \&{__PACKAGE__.$func}; goto &$func; } 1;
    #!/usr/bin/perl; use MyConstants qw(AUTOLOAD); use strict; use constant { NIL => -1 }; my @ary = qw(ene mene muh); print join(" => ", @ary[FOO(),NIL()]),$/; __END__ mene => muh

    ... to get the constants when they are needed, at the expense of explicitly marking the constants as function calls (they are that anyways), e.g. FOO(), which otherwise would be interpreted as barewords.

    But I myself would consider that bad practice, since it is too obscure. I'd use that technique only for development, dump the imported constants in the sub AUTOLOAD and, in the final version, use that output to import the constants explicitly in the importing package.