Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Importing constans and variables when "require"ing

by bliako (Monsignor)
on Feb 22, 2019 at 21:48 UTC ( [id://1230428]=perlquestion: print w/replies, xml ) Need Help??

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

Good Monks warm salutations,

I am trying to require a module and use a constant and a variable from it but I get an error and a warning respectively.

This is the module:

# XYZ.pm package XYZ; use strict; use warnings; require Exporter; our @ISA=qw/Exporter/; our @EXPORT_OK = qw/PI CONST/; our $PI = 3.14; use constant CONST => 10.10; 1;

And this is how I require it:

# example.pl use strict; use warnings; use lib '.'; require XYZ; print "PI=".$XYZ::PI."\n"; print "CONST=".XYZ::CONST."\n";

I get an error:

Bareword "XYZ::CONST" not allowed while "strict subs" in use at exampl +e.pl line 13. Execution of example.pl aborted due to compilation errors.

Now, if I comment out the line using CONST then I get this warning:

Name "XYZ::PI" used only once: possible typo at example.pl line 11. PI=3.14

I have deliberately not used XYZ->import(qw/PI CONST/); as I prefer to use the full name of variables and subs from other modules. But it makes no difference as to the warnings and errors mentioned above.

Can you please shed some light?

Replies are listed 'Best First'.
Re: Importing constans and variables when "require"ing
by Paladin (Vicar) on Feb 22, 2019 at 21:57 UTC
    require is evaluated at run time. use is evaluated at compile time. Your errors are coming at compile time, and since the require hasn't been evaluated yet, the compiler can't know about what's in the XYZ.pm file at that time. Change your require to use, and you should be good.

      Fair enough, but why does it work and print the value of $PI if I comment out the use of CONST in main entirely (i.e. main's last line)? Also adding a sub in XYZ and calling it from main works ok. Is it because it can live without unresolved subs until it actually has to call them? But it has to resolve each and every variable before execution (when using strict at least)?

      The long story is that I ended using require because I have a module which overrides a core sub (sleep) via a BEGIN block. I need that to apply for ALL subsequent modules, mine or foreign, and I kind of reasoned that loading everything else at runtime (via require) will make sure that this is satisfied and sleep is overriden. Now I am not sure whether a module used via another module is using the overriden sleep version.

        > Fair enough, but why does it work and print the value of $PI if I comment out the use of CONST in main entirely (i.e. main's last line)?

        Strict has 3 effects, one (subs) is to restrict the use of barewords to only known subs. Constants are implemented as subs and need to be known at compile time.

        See also "use subs "

        This doesn't necessarily mean that the sub known at compile time is also the called sub, because resolution happens at run time. (Keep in mind that you can redefine subs dynamically, this will just update the reference in the symbol table)

        Any sub called with & or trailing () is not a bareword anymore, and not effected by strict.

        Another effect of strict (vars) is to enforce pre declaration of unqualified variables with my or our.

        But your variables are fully qualified. And barewords are not variables (under strict).

        Update

        It all becomes much easier if you first understand how Perl works without strict, an why these restrictions need to be done.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Importing constans and variables when "require"ing
by AnomalousMonk (Archbishop) on Feb 22, 2019 at 22:31 UTC

    As Paladin pointed out, this is a compile-time-versus-runtime thing. Furthermore, since you want to fully qualify all the module symbol names anyway, I see no reason to bother with any Exporter stuff.

    File XYZ.pm:

    # XYZ.pm package XYZ; use strict; use warnings; # require Exporter; # # our @ISA=qw/Exporter/; # our @EXPORT_OK = qw/$PI CONST/; our $PI = 355/113; use constant CONST => 42; 1;
    Output:
    c:\@Work\Perl\monks\bliako>perl -le "use strict; use warnings; ;; use lib '.'; use XYZ; ;; print 'PI = ', $XYZ::PI; print 'CONST = ', XYZ::CONST; " PI = 3.14159292035398 CONST = 42
    (Disambiguation of  XYZ::CONST not needed here.)

    Update: BTW: Doing a require in a BEGIN block
        BEGIN { use lib '.';  require XYZ; }
    would have had the same phasing effect as the use statement.


    Give a man a fish:  <%-{-{-{-<

Re: Importing constans and variables when "require"ing
by Perlbotics (Archbishop) on Feb 22, 2019 at 21:58 UTC

    use const does it's trick by creating a sub that returns a then "constant" value. Use the function call parents to honour that fact in the context of the print statement at compile time.

    print "CONST=" . XYZ::CONST() . "\n"; # ^^-here

      ok that's a neat trick

Re: Importing constans and variables when "require"ing
by tobyink (Canon) on Feb 23, 2019 at 11:06 UTC

    Others have hopefully helped you understand what the issue is. I'll add this:

    use XYZ ();

    By specifying an explicit empty list at the end of the use statement, Perl will avoid importing anything from the module, but will still load it at compile time. So XYZ::CONST will work.

      that's useful for me: I usually prefer using the full name of foreign subs anyway. thank you

Re: Importing constans and variables when "require"ing
by LanX (Saint) on Feb 23, 2019 at 05:13 UTC
    I'm confused ...

    >

    print "PI=".$XYZ::PI."\n"; print "CONST=".XYZ::CONST."\n";

    Importing means aliasing symbols from an exporting namespace into an importing namespace.

    Since you are fully referencing the exporting namespace XYZ, you won't need any importing.

    Update

    A simple do File would be enough.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Importing constans and variables when "require"ing
by BillKSmith (Monsignor) on Feb 22, 2019 at 22:55 UTC
    Paladin has identified the problem. His solution of replacing 'require' with 'use' implicitly calls 'import' (which you stated that you do not want). You can do your require at compile time without the side effect by placing the 'require' statement in a BEGIN block. The module does not have to explicitly export anything because exports will be ignored.
    Bill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-26 02:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found