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

Which "use" statements in a module do "bubble up" to the callers? [SOLVED]

by Nocturnus (Beadle)
on Aug 31, 2017 at 14:31 UTC ( [id://1198411]=perlquestion: print w/replies, xml ) Need Help??

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

Dear monks,

I am searching your wisdom or an excerpt from your library regarding the following question:

Suppose I have a module called Test::Test1, and in that module, at the very beginning, I have the statements "use warnings;" and "use constant TESTCONST => 1;".

Furthermore, I have a Perl script called script.pl which uses that module, i.e. I have "use Test::Test1;" at the beginning of script.pl. Then, obviously, using the constant TESTCONST in script.pl works as expected, but warnings do not seem to be enabled in script.pl.

Is there an overview about which of the various "use ..." statements, if given in a module, make the module's callers behave like if the "use ..." statements was given directly in the caller?

Of course, the deeper sense of my question is that I have dozens of scripts which all should use the same basic settings regarding warnings, strict mode, utf8 and a bunch of others.

Thank you very much,

Nocturnus

  • Comment on Which "use" statements in a module do "bubble up" to the callers? [SOLVED]

Replies are listed 'Best First'.
Re: Which "use" statements in a module do "bubble up" to the callers? (updated)
by haukex (Archbishop) on Aug 31, 2017 at 15:44 UTC
    obviously, using the constant TESTCONST in script.pl works as expected

    Actually, that's not so obvious from what you've written so far. use Test::Test1; on its own should not cause TESTCONST to be exported from Test::Test1 into the current package unless there is additional code you haven't told us about, such as if you're using Exporter or your script.pl begins with package Test::Test1;. (Update 2: Ok, as per your reply, you don't have a package Test::Test1; at the top of Test1.pm, that explains it too. I wrote this post with the assumption that your Test1.pm begins with package Test::Test1;.)

    Is there an overview about which of the various "use ..." statements

    Unfortunately, no. There are some rough rules of thumb, such as modules whose names are lowercase are "pragmas" and their effect is often (but not always!) lexically scoped (warnings and strict being the two most common), and regular modules will usually at most export a few functions into your package (although there are lots of exceptions to this rule of thumb). So the short answer is you'll have to look at each module's documentation to see what useing it will do. The long answer is:

    Once you understand what's going on under the hood, the mechanisms that Perl uses for modules and pragmas are actually relatively transparent in that there isn't a ton of magic involved, and one can see all the moving parts. When you use a module that you write yourself, here's a rough overview of the mechanisms involved:

    1. When you write use Test::Test1;, then what Perl actually does is BEGIN { require Test::Test1; Test::Test1->import(); } (documented in use), and what require does is explained in detail in its docs, but simplifying a bit, it will search for a file named Test/Test1.pm in the directories listed in @INC and parse and run that file if it hasn't previously done so. Usually, this file will contain a package Test::Test1;, although there is no hard requirement for this. Then, Test::Test1->import() means to call the sub import in the package Test::Test1, passing the string "Test::Test1" as the first parameter (a "class method"), and if there are any parameters in the use statement after the module name and version, pass those as the remaining arguments to import. So you see the basic mechanism here is finding a file, loading it, and calling a sub in that file, which is then free to do whatever it wants, and this is where the "magic" of ex/importing happens.
    2. While you can write a sub import yourself*, that's uncommon because there are several standard implementations, a very common one being the one provided by Exporter. So if in your package Test::Test1; you have written our @ISA = qw/Exporter/;, use base 'Exporter';, or use Exporter 'import';, then your package will be getting Exporter's sub import. What Exporter's import will do is, again very simplified, take the subs and variables you have listed in the package variable @Test::Test1::EXPORT (among others), and install those in the package that called the sub import, i.e. in the package that called the use.
    3. Now as for your question, the effect of use warnings; is limited to the enclosing lexical scope, which in this case is the file, which is why it only affects your Test1.pm. The effect of use constant TESTCONST => 1; is to set up a sub TESTCONST () { 1 }, which means that just like any other sub this definition should be limited to the current package (it is Test::Test1::TESTCONST()), unless you've set up an export/import mechanism like the one I described above to copy it out of that package and into whatever package script.pl uses (main by default).

    So you can have modules that export functions in the way I described above, you can have modules that export nothing (usually OO modules), or your own custom "pragmatic" modules that, like warnings, only have an effect in the current lexical scope (documented in perlpragma), or even mixes of these kinds of modules. A close reading of perlmod and the other documentation referenced therein should explain most of this in more detail. Because Perl is very flexible in what it allows module authors to do, it isn't easy to give some general rules as to how modules act, beyond some guidelines and best practices about how modules should be written, and based on that some rules of thumb of what to expect. So you'll have to look at the documentation of each of the modules to see what effects useing them will have. Luckily, most modules have good documentation and the "Synopsis" and further descriptions at the top will usually tell you right away.

    I have dozens of scripts which all should use the same basic settings

    The recent thread Code Reuse and the threads linked therein (like use y) should help you there. In particular, I have myself used Syntax::Collector and it's a nice module. The only minor drawback is that it uses Exporter::Tiny instead of Exporter, so you can't export variables, only subs (including constants). And just for completeness, here's the code that does what you want without using an extra module:

    package Test::Test1; use warnings; use strict; use constant TESTCONST => 123; use base 'Exporter'; our @EXPORT = qw/TESTCONST/; sub import { warnings->import; strict->import; __PACKAGE__->export_to_level(1, @_); return; }

    Then, in code that does use Test::Test1;, warnings and strict are enabled and sub TESTCONST is exported as well.

    * Update: The basis of what most sub import implementations do is described in the section "Symbol Tables" in perlmod - basically you take the entry for the sub whatever in the current package, &Current::Package::whatever, and copy it to the symbol table of the target module (e.g. main), so that both &main::whatever and &Current::Package::whatever refer to the same piece of code. For completeness, here is an extremely minimalistic implementation of sub import, but this is the basis of what Exporter and related modules do:

    our @EXPORT = qw/ ... /; sub import { my $callerpackage = caller; for my $export (@EXPORT) { no strict 'refs'; *{$callerpackage."::".$export} = \&{$export}; } }

      Thank you very much for that fantastic explanation!

      You are right, it's all there. I don't know what my problem was; I have read the documentation for "use warnings;" and "use strict;" multiple times before asking, and both quite at the beginning state they are lexically scoped. The documentation for "use warnings;" even states the reason: To prevent "leaking" to callers and other packages ... no idea what has been wrong with me. Probably I have got wrong the term "lexically scoped".

      My next problems were "use utf8;" and "use feature unicode_strings", but I now know that "use utf8;" and "use feature ..." are lexically scoped as well.

      In my module, there are also some commands to set the binmode for STDIN, STDOUT and STDERR. Since I now have understood that there will run a do(module_file_name) when the module is loaded, I can be sure that those commands will be run whenever that module is used - one more understanding problem solved.

      The only thing which I am still wondering about is that the constants are indeed in my script.pl, without having them exported from the module. But I think this is due to the fact that I have no "package ..." statement in that module (yet). Yes, I know, bad style, but still just testing at the moment ...

      And finally, I have decided that I (for the moment) just copy all common "use ..." statements from my module into every script. It is ugly, but it is not too much work. It is very good to know how I could solve this in a clean way, though. I'll do that later.

      Again, thank you very much!

      Nocturnus

        there are also some commands to set the binmode for STDIN, STDOUT and STDERR

        BTW, you can use the open pragma with its :std option for this as well.

        The only thing which I am still wondering about is that the constants are indeed in my script.pl, without having them exported from the module. But I think this is due to the fact that I have no "package ..." statement in that module (yet). Yes, I know, bad style, but still just testing at the moment ...

        Correct on both that it's due to the missing package (that means everything is happening in the default package main) and that it's bad style ;-)

Re: Which "use" statements in a module do "bubble up" to the callers?
by LanX (Saint) on Aug 31, 2017 at 16:09 UTC
    What you request is non-standard behavior, hence no module should ever automatically "bubble up" two caller levels to the "grandparent" *

    It's the module in the middle which could use tricks to "transport" (hopefully well documented) behavior from the used "child" module to the to the "parent" caller.

    For instance taking your examples

    • constants are implemented as functions with an empty prototype, hence can be exported like all normal functions.
    • warnings and strict can be propagated like explained here ²

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

    *) though it's possible, by exporting import , but doing so means mangling with the dark side, young padawan.

    ²) this should (?) work with all modules depending on Exporter

Re: Which "use" statements in a module do "bubble up" to the callers?
by BillKSmith (Monsignor) on Aug 31, 2017 at 15:04 UTC
    This is intentionally not allowed. Refer to the official documentation for warnings: Description
    Bill
Re: Which "use" statements in a module do "bubble up" to the callers?
by Anonymous Monk on Aug 31, 2017 at 14:53 UTC
    A similar question was just asked. Modules like strict and warnings are lexically scoped pragmas that disappear at the end of the current block. It takes trickery to work around that behavior, and you probably don't want to go there. Have you looked at Modern::Perl? constant is file-scoped. If you want your constants visible outside the file where you define them, you need to use Exporter. Perl's module system is very flexible, but I'm afraid that means that it's not possible to give you a simple answer.
      constant is file-scoped.
      Sorry, that's wrong, it's package-scoped. Usual practice is to define one package per file, which is the source of my mistake.
        I believe that constants are implemented as functions and have package scope the same as other functions.
        C:\Users\Bill\forums\monks>type scope.pl use strict; use warnings; use constant PI => 3.14; my $pi = PI; package B{ my $pi = PI; } C:\Users\Bill\forums\monks>perl scope.pl Bareword "PI" not allowed while "strict subs" in use at scope.pl line +6. Execution of scope.pl aborted due to compilation errors.
        Bill
Re: Which "use" statements in a module do "bubble up" to the callers? [SOLVED]
by Nocturnus (Beadle) on Aug 31, 2017 at 17:00 UTC

    Well, a big thanks to everybody who helped so fast!

    I think I've got the essence of what you have written, and that problem is solved for me. Thus, I have marked this thread as solved.

    Cheers,

    Nocturnus

Re: Which "use" statements in a module do "bubble up" to the callers? [SOLVED]
by LanX (Saint) on Sep 01, 2017 at 14:23 UTC
    For completeness, you can use a do FILE (and consequently a require and use if the code is included before the package statement of the pm file) to eval a file in place.

    Like this you can technically include package variables, constants and functions.

    Most people would consider this a dirty hack.

    And it will not export use s of file scoped pragmas and modules and lexical variables.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: Which "use" statements in a module do "bubble up" to the callers? [SOLVED]
by Anonymous Monk on Sep 01, 2017 at 14:26 UTC
    A key thing to know about Perl is that the use directive is, shall we say, overloaded. Sometimes it is a file-inclusion directive similar to require, and sometimes it is a pragma ... an instruction to the compiler ... and there is no consistency among the pragmas. So it goes. Some language-implementors chose to use different keywords for the different cases, but long ago Perl did not. Even third-party packages can do it, as with the use Moose and no Moose directives that can fill source-code where Moose is being employed. You can't make generalizations about use. You have to know from context what each instance means.
      use is require followed by import, no more and no less. import is defined by the module in question, and can do whatever it wants. Normally, it adds stuff to the caller's symbol table, but it doesn't have to.
        use is require followed by import, no more and no less.

        I agree that the parent could be worded better, but if we're being nitpicky, that's also not quite right. use Module VERSION LIST (where both VERSION and LIST are optional) is equivalent to:

        BEGIN {
          require Module;
          Module->VERSION( VERSION );  # if VERSION was specified
          Module->import( LIST );      # *except* when LIST is "()"
        }
        

        And use VERSION; requires a minimum version of Perl. That's all use does, and whether the Module is a prgama, regular module, or whatever else, is up to that module and its import, not use. Update: Well now I need to nitpick myself - use VERSION; also enables the feature bundle for that version and strict if the version is 5.12 or greater. Also, it should be noted that if Module doesn't have a sub import, no error is raised.

Log In?
Username:
Password:

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

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

    No recent polls found