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

I have a module that represents a configuration file object, say ConfigFile.pm which reads a Configfile.txt file. The overall application is tournament scoring and the ConfigFile contains things like tournament names, various "handicap" values, etc. There are a lot of ways to go wrong when writing the ConfigFile so I have a test/validator program. The output of this test program is not a simple pass/fail module test, but is rather a development tool to inform the user about potential inconsistencies with the purpose of ensuring that the overall program is going to do what the user intends (which may not be what the ConfigFile instructs the program to do!).

Rather than having a separate validator program, I'd like to have the module behave differently when it is executed perl ConfigFile.pm rather than when it is "used", ie: use ConfigFile.pm.

I remember that there is an easy way for the module to know this difference but I have been unable to find this "trick". So my question is how to I do this?

Update:Thanks to Choroba, my code will become: validate() unless caller;

PS: Sorry for long explanation, but I wanted to head off any XY discussion. Yes, this is what I want. validate() is already a method for the object, so I can get rid of an extra .pl file.

Update 2: I thank the Monks for a robust discussion. I've learned at least a couple of things and I thank you all for that.

Replies are listed 'Best First'.
Re: Difference between executing and "using" a .pm file
by choroba (Cardinal) on Mar 30, 2021 at 19:09 UTC
    Check caller.

    print caller ? 'required/used' : 'running as script';

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Thank you!

      caller says "Returns the context of the current pure perl subroutine call. In scalar context, returns the caller's package name if there is a caller"

        The concept - like already mentioned by pryrt - is called "modulino" and was popularized by Brian D Foy IIRC.

        I'm using it regularly to run various tests when developing a module.

        Like this I can always hit F5 in my editor, no matter in which file of a project I am.

        And the current test-procedure is on top of my module in an

        unless (caller()) { BLOCK }

        Like this I don't need to always change a different make file to test the function I'm currently changing.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: Difference between executing and "using" a .pm file
by pryrt (Abbot) on Mar 30, 2021 at 19:11 UTC
    I remember that there is an easy way for the module to know this difference

    were you thinking of modulino?

Re: Difference between executing and "using" a .pm file
by ikegami (Patriarch) on Mar 31, 2021 at 02:43 UTC

    There are a couple of problems with executing a module as a modulino. And it's totally unnecessary. Load the module properly.

    perl -e'use ConfigFile; ConfigFile::validate()'
    which can be written as
    perl -MConfigFile -e'ConfigFile::validate()'

    Seeking work! You can reach me at ikegami@adaelis.com

      My thought was just: perl ConfigFile.pm where, when run as an executable, it runs the validate() routine.

      I am just looking for simple syntax for my user which eliminates a trivial driver program. This is probably not that big of a deal. And it could also be that this confuses the issue even more and is a bad idea! It could wind up being that I need to build a GUI to assist generation of this config file.

        Yes, and to that I said: There are a couple of problems with executing a module as a modulino. And it's totally unnecessary. Load the module properly.

        Seeking work! You can reach me at ikegami@adaelis.com

Re: Difference between executing and "using" a .pm file
by 1nickt (Canon) on Mar 30, 2021 at 19:08 UTC

    Are you thinking of %INC?

    Hope this helps!


    The way forward always starts with a minimal test.
      I believe %INC is unaffected by this execution difference. However Perl is so wonderfully introspective, I just need to ask "who called me?". If I am being executed from the command line, then nobody did!

      Update: I see this post got a -1 vote. If you did that, then why don't tell us all why you did that?

Re: Difference between executing and "using" a .pm file
by perlfan (Parson) on Mar 30, 2021 at 19:55 UTC
    Generally speaking, a modulino uses the .pl extension and is included in a library context with a require (as in, require '/path/to/my/modulino.pl';). If you already have a bonefide module as .pm, then you'll necessarily want to create a commandline driver that will use this module, handle commandline arguments, then do something useful with the functionality encapsulated with the module. You don't want to put the caller check in file scope of the .pm then call that .pm as you would a .pl script.

    So to make your use case consistent with a modulino approach, rename your .pm to .pl; keep the caller based context dispatching and you can call your .pl script a modulino.

    But this is sort of going backwards. Like I said above, if you have a .pm file already; just use it in a .pl. The whole point of a modulino really is ephermal; sure they can be long lived, but it's most useful when refactoring legacy code bases into a modular/library centric approach.

    Another characteristic of your .pm not being a fully encapsulated module (and maybe inappropriately serving as a modulino) is if you have any commandline argument processing anywhere in it - be it ad hoc, Getopts or what have you. This sort of @ARGV munging typically belongs exclusively inside of a .pl (including one that is a modulino).

      Generally speaking, a modulino uses the .pl extension

      Interesting. Because the modulino link I provided was actually in my browser history because of your Re: Need to know the process to implement perl script into web application server.... and that link you provided shows a file named examples/modulino.pm and he runs it as perl modulino.pm. So it's not completely unheard of to have the modulino as a .pm, not a .pl

      It seems there are really two use cases for modulino:

      1. having a script, and wanting to slowly turn it into a module (ie, your use case)
      2. having a module, and wanting to do something without having to write a separate .pl to call it, like validate, test, or run under default conditions (ie, the case that gszabo seems to be espousing in the article, and that Marshall wants and LanX gave examples of)
      Both seem reasonable uses of the concept, to me.
        I think this

        Rescue-legacy-code-with-modulinos

        is the central article on the topic with a lot of links and historical context. Especially b/c Brian states that he didn't invent but popularized the concept. (he even cites a Perlmonks' thread as earliest reference for the term "modulino")

        He describes it primarily as a way to perl Module.pm with a meaningful effect. (A)

        But in the second part of this article he describes the other way round from initial require script.pl to renaming pl -> pm at the end. (B)

        I.O.W. how he's using this technique to transform legacy code into modules.

        Actually that's quite a interesting and powerful strategy. I'm certain I've seen this article multiple times before, but can't remember reading this part anymore.

        And I think that's not surprising. We have to realize that this (B) direction involves far more refactoring, while the former (A) can be already achieved with just one single additional line.

        I'd say it's safe to say that >95% of all modulinos out there belong to the A-category of runnable modules, and that's what the majority remembers.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        > he runs it as perl modulino.pm

        I didn't realize that, but that just goes to show you TIMTOWDI :). And I agree with your use cases above; though I use it often for case #1 and have never had the need for #2. Thank you.
      You wrote: "If you already have a bonefide module as .pm, then you'll necessarily want to create a commandline driver that will use this module, handle commandline arguments, then do something useful with the functionality encapsulated with the module.".

      Yes, that is actually what I have now, except that there are no command line arguments. If there were any command line args, then I would keep what I have (a very short driver program). All of this code that spews out explanations to the user about the config file is already part of the object. This is not a module test target, it is more analogous to a regex decompile thing.

      At the end of the day, I may or may not do this. But if I want to do it, I know how to do it. This is actually not a "big deal" either way. I have already released the 6th year code and as such this is more of an academic question. However major revisions are planned for year #7. I've got months to think about this. I just wanna understand the options that I have.

        > I just wanna understand the options that I have.

        Very good. Obviously don't take my tone to mean this is the only use them or way to do it. I like talking about modulinos any chance I can get, though. Neat stuff.
Re: Difference between executing and "using" a .pm file
by Anonymous Monk on Mar 31, 2021 at 02:37 UTC