Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Using constants...

by willjones (Sexton)
on Oct 29, 2009 at 17:49 UTC ( [id://804003]=perlquestion: print w/replies, xml ) Need Help??

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

I want to have a file where I define a set of constants and then be able to require that file from others and have those constants available. For some reason though I can't seem to get this to work. I have something like this setup...

constants.pl
use constant { MY_CONSTANT1 => 1, MY_CONSTANT2 => 2, MY_CONSTANT3 => 3, MY_CONSTANT4 => 4 }; sub useConstants { #able to use constants fine in here... my $var = MY_CONSTANT4; print "$var\n"; #outputs '4' } 1;

main.pl
#!/usr/bin/perl #use strict; # If I uncomment this line it won't compile because it c +laims MY_CONSTANT3 is a bareword and not a constant. require "constants.pl"; #if I call useConstants this sub can use them just fine. useConstants(); #However if I try to use a constant that should've been defined in con +stants.pl here it won't work! my $var = MY_CONSTANT3; print "$var\n"; #outputs 'MY_CONSTANT3' !! Why won't it output '3'? exit 1;

output...
me@mybox:/test >perl main.pl 4 MY_CONSTANT3 me@mybox:/test >

If I add a use strict; in to the top of main.pl this won't even compile because it says MY_CONSTANT3 is a bareword and isn't allowed. I don't understand. Isn't constants.pl in the main namespace too? Why wouldn't it still be visible? What can I do to accomplish having a set of constants that can be shared across multiple files?
Thanks,

Replies are listed 'Best First'.
Re: Using constants...
by Joost (Canon) on Oct 29, 2009 at 18:31 UTC
Re: Using constants...
by ikegami (Patriarch) on Oct 29, 2009 at 18:08 UTC

    If I uncomment this line it won't compile because it claims MY_CONSTANT3 is a bareword and not a constant.

    Correct. At compile time, there is no function named MY_CONSTANT3, so MY_CONSTANT3 is treated as a string literal. This is obviously not what you want, so strict lets you know.

    You need to execute require "constants.pl"; before my $var = MY_CONSTANT3; is compiled.

    Since using require to load something that doesn't have a package makes no sense, I'll fix that at the same time.

    #!/usr/bin/perl use strict; BEGIN { do "constants.pl"; die $@ if $@; } my $var = MY_CONSTANT3; print "$var\n";

    By the way, I removed the exit 1; since there's no reason to signal an error occured.

Re: Using constants...
by jakobi (Pilgrim) on Oct 29, 2009 at 17:52 UTC

    perldoc -f use as of 5.10.0/5.10.1 gives this hint in the section on use constant; use strict; et al:

    Some of these pseudo-modules import semantics into the current block scope (like "strict" or "integer", unlike ordinary modules, which import symbols into the current package (which are effective through the end of the file).

    which misled me into stopping to think way too early: whatever this documentation scrap might refer to, it's not the applicable here -> see my question in Re^3 below.

    cu & sorry, Peter -- hint was wrong, be careful of contagious confusion.

      Actually, constant is like an ordinary module. It exports functions, it doesn't change semantics, and the effects are tied to the package and not the caller's scope.

        ikegami's right as a BEGIN{require 'constants.pl'} (thanx!) or even a simple peek at %main:: does show.

        But I'm still wondering about this section in perldoc -f use:

        Because this is a wide-open interface, pragmas (compiler directives) are also implemented this way. Currently implemented pragmas are:
              use constant;
              use diagnostics;
              use integer;
              use sigtrap  qw(SEGV BUS);
              use strict   qw(subs vars refs);
              use subs     qw(afunc blurfl);
              use warnings qw(all);
              use sort     qw(stable _quicksort _mergesort);
        
        Some of these pseudo-modules import semantics into the current block scope (like "strict" or "integer", unlike ordinary modules, which import symbols into the current package (which are effective through the end of the file).

        Let me attempt to make sense of it:

        Now a BEGIN{require "constants.pl"} basically turns contents.pl into a module. Add a do "y" somewhere near the end in main.pl. Create this file y and have it just print STDERR keys %main::. Copy it to a file z and prepend BEGIN{do "main.pl"}. Run perl -e ./z. Wonder. Check Exporter documentation and do a similar little test with imported symbols. And start WONDERING.

        • use strict; obviously is well behaved and doesn't mess with other files or blocks outside its enclosing lexical scope. Ok. Should the same for stuff like integer et al.
        • Function definitions in %main:: are valid beyond the end of the file.
        • If file A requires a file B, which in turn says 'use ... qw/function/;', the function by default is visible also in the file A. Using Exporter doesn't localize things, and the imported functions and symbols are also visible in files other than the file containing the actual use statement (read: way beyond end of enclosing file).

        I'm now fully confused, and it's not the missing parens in the quoted section above:

        • What does the above quote from perldoc -f use try to say?
        • What exactly might effective through the end of file refer to? Especially given the the mention of ordinary modules!?
        • What kind of (importing symbols in package name space from?) ordinary modules has file scope!?

        Any ideas on what is actually meant?

        cu & thanx, Peter -- --INT due to confusion spell.
Re: Using constants...
by Oleg_T (Initiate) on Nov 18, 2009 at 09:08 UTC
    constants.pl:
    use constant test => 3; 1;
    test.pl:
    #!/usr/bin/perl require 'constants.pl'; print main->test;
    print 3
      That defeats the purpose, he wanted to export constants

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://804003]
Approved by Perlbotics
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-19 02:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found