Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

sub running on use statement

by Anonymous Monk
on Dec 02, 2014 at 04:28 UTC ( [id://1108914]=perlquestion: print w/replies, xml ) Need Help??

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

Subroutines in a module have started running themselves on the "use" statement. I've not run across this behavior before and am stumped. Has anyone else seen this happen ?

It's such an odd problem that I wouldn't believe it was happening if I hadn't spent most of the day going over the code. I've even tried the absurd - copied the module text into NotePad, saved it, closed it, deleted the module file, then recreated by opening the NotePad file and copying the text into the newly created empty module file.

I did that in case there was some file error that inserted some unseen control character into the original module file. Bizarre, I know, but I tried it.

I can't duplicate this on another module, or on any running sample code to post. I've tried, and it won't happen.

I tracked it down with a print statement in the module. The print statement runs on the "use ScrewyModule" statement (not the actual module name, I've called that module many unprintable things today). Not just when a subroutine in the module is called - the print statement in the subroutine in that module runs on the "use ScrewyModule" statement.

I tested this because I couldn't really believe it was happening. I put in print statements in the module subroutines, and before and after the "use ScrewyModule;" statement to confirm this. Like so :

I inserted a print statement like the following into any subroutine in the module - didn't matter which one, I got the same result :

sub ScrewySubRoutine { print "\n\nrunning the sub\n\n"; }

Then in the main script I added 'before' and 'after' print statements around the suspect "use" statement :

#!C:\Perl\bin use diagnostics; use strict; print "\n\nbefore use\n\n"; use ScrewyModule; print "\n\nafter use\n\n";

Running that main script with these print statements in the module and main script, this would be the output :

before use

running the sub

after use

If I comment out the "use ScrewyModule;" statement, this would be the output :

before use

after use

I'm really just wondering if anyone has seen this before, and if so, remembers what caused it.

Replies are listed 'Best First'.
Re: sub running on use statement
by NetWallah (Canon) on Dec 02, 2014 at 05:22 UTC
    Another possibility is that ScrewyModule.pm has a sub import() that calls other subs:
    package ScrewyModule; sub import{ test(); } sub test{ print "in ScrewyModule.pm\n"; } 1;
    In this case test() gets called (via import) when the module is "use"d.

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

      Yes, that's what I have in the module. Quite a few, actually.

      The sub-routine that I noticed this printing on is recursive, calling itself to fill an array with all the files in a directory tree. When that recursive subroutine was called from another module, it printed when I didn't expect it.

      One of the scalars passed by reference to that recursive subroutine is the parent directory to search. I'd inserted a print statement just after the references were taken from "$_" to confirm that the parent directory was correct.

Re: sub running on use statement
by GrandFather (Saint) on Dec 02, 2014 at 05:01 UTC

    Your story isn't consistent. For a start use statements are executed during the compilation phase before any "normal" code is run so the output you suggest you see is not what I'd expect to see. Indeed, when I run the following code:

    ####### ScrewyModule.pm package ScrewyModule; use strict; use warnings; ScrewySubRoutine(); sub ScrewySubRoutine { print "running the sub\n"; } return 1; ####### noname.pl #!C:\Perl\bin use diagnostics; use strict; print "before use\n"; use ScrewyModule; print "after use\n";

    I get:

    running the sub before use after use

    as expected.

    Note though that I have an explicit call to ScrewySubRoutine in the module. If I omit that line then ScrewySubRoutine does not get called. I suspect that you have a call to ScrewySubRoutine in your module code outside any sub. Maybe you should run your code through PerlTidy to make sure the indentation is correct then go looking for unexpected code?

    Perl is the programming world's equivalent of English
      You're correct - the output is as you state. Apologies for the error. I was a bit fuzzy at the end of a long day.

      You're also correct about the calls to other subs in other modules. I've had a practice of taking segments of code that I use in several modules or scripts and putting them into subs in another module.

      Thanks for your response. You did clear up something that I was uninformed about with regard to sub-routines and modules.
Re: sub running on use statement
by LanX (Saint) on Dec 02, 2014 at 05:06 UTC
    Obviously somewhere in ScrewyModule.pm you are calling ScrewySubRoutine()

    The whole module is evaled, so if anything is written outside a 'sub', it will be executed imidiately after "use ScrewyModule" happend.

    If this doesn't help, try raising a warning instead of printing. Try showing the call-chain to isolate where it origins. (see Carp )

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

      Spot-on. I've got a number of modules which contain sub-routines that are called, including calls to and from other sub-routines in other modules.

      The one causing the problem is recursive and calls itself to fill an array with all the files found in a directory tree. Calling that sub-routine from another module is where I ran into the printing oddity ( odd to me ) when testing it out.

      I'm still fuzzy on the evaluation part. I had thought that the evaluation was just checking the script for syntax and reference errors - essentially, "static" script problems. I didn't think the evaluation also includes running the sub-routines to check for run-time errors.

      Is that what actually happens - that Perl does a "test-run" of the sub-routines in addition to checking for syntax and reference errors ?

        Is that what actually happens - that Perl does a "test-run" of the sub-routines in addition to checking for syntax and reference errors ?

        There is no "test-run" when a module is use-ed. Basically, Perl does what you use the module to tell it to do, but it does it at compile time. Usually you just tell Perl to define subroutines using sub, a fairly quiet process, or maybe define some global or lexical variables, likewise quiet. However, you can do other things, like building complex data structures — which, according to your other posts, you seem to be doing! You could call a built-in function like
            print 'string';
        and  string would be printed at compile time, as pointed out in other posts. You can call any (defined) function and it will execute.

        See "BEGIN, UNITCHECK, CHECK, INIT and END" in perlmod for more info on controlling when things get executed WRT compile versus run time.

        Every module is evaluated at use time, but normally a module contains only sub definitions, so nothing is run then (except import() )

        BUT if you do unusual stuff like grandfather demonstrated in his first example ScrewyModule.pm , i.e. code is outside of any sub at top level then something like you described can happen.

        But that's speculation cause you are not showing us any code.

        So please either

        • play around with the examples given to see if it might happen to you
        • use Carp (see cluck() and confess() ) to force a stack trace at the beginning of the "weird" sub to track down the location of your problem.
        • shorten your problem manually to code isolating your problem and show.

        Anything else won't lead to results.

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: sub running on use statement
by choroba (Cardinal) on Dec 02, 2014 at 09:53 UTC
    Any source filter involved?
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Spooky. I do have a source filter running, but I'm nowhere near as knowledgeable in Perl as I will be (someday). So I expect you mean something different, something that I don't yet understand. After reading your reply, I looked up Perl Source Filters. No surprise to me, it's a concept I'm not advanced enough in Perl to even try out :)

      The confluence of that term and the name of one of my directories was an interesting coincidence.

      Or maybe it wasn't a coincidence...perhaps you're not لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ as you claim to be ... ( insert spooky music here )

        Actually, don't bother with Perl source filters. They tend to introduce very nasty bugs and unexpected behavior. Interesting for performing some cool party tricks, but generally not recommended for production code.

        Perl is the programming world's equivalent of English
Re: sub running on use statement
by Laurent_R (Canon) on Dec 02, 2014 at 07:33 UTC
    Please show the code of the full module, not just a function belonging to it. Or, better yet, a cut-down version of the module still exhibiting the behavior you described.
Re: sub running on use statement
by Anonymous Monk on Dec 02, 2014 at 05:02 UTC
    Post the output of  perl -V

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1108914]
Approved by lidden
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: (5)
As of 2024-04-19 13:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found