Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Call sub in variable module

by tel2 (Pilgrim)
on Nov 07, 2016 at 00:58 UTC ( [id://1175392]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

Let’s say I’m doing this in my main script:

require mydir::mymod123; $result = mydir::mymod123::mysub();
And the module looks something like this:
package mydir::mymod123; sub mysub { ...etc... return $x; } 1;
The above works, but the "123" part could be any of hundreds or thousands of numbers, so I’ll store that number in $modno, and I can "require" the module like this:
$modno = 123; # Just for simplicity. Actually this number will +come from a database. require "mydir/mymod$modno.pm";
That seems to work, but how can I call mysub() now?

I’d like to avoid using a dispatch table please, because it could get very long, and I don’t want to have to modify the code each time a new module is added to mydir.

Also, if each module will always contain only 1 sub, do they need to have a sub at all? If not, how can they be written & called without a sub?

Thanks.
tel2

Replies are listed 'Best First'.
Re: Call sub in variable module
by GrandFather (Saint) on Nov 07, 2016 at 02:47 UTC

    Why? mydir::mymod123 smells awful. Tell us about the big picture because at the moment it looks like you have come up with a very common awful solution to some problem. We may be able to help you come up with a much better approach that will eliminate the need for numbered modules and other such weird games.

    Premature optimization is the root of all job security
      My apologies for the apparent stench, GrandFather.

      mydir::mymod123 is just for demonstration.

      The $modno will probably not end up being a number at all, that was also for demonstration.

      Basically, some users will need different functionality from others, and I just want to "require" & call the appropriate bits.

        You still haven't given us a big picture. I can imagine various scenarios where you are providing an engine (web site, build system, data server, ...) where you want to provide a plug in system for users. There are well established techniques for doing those jobs and none of them require the engine to know implementation details of the plug ins.

        Maybe you have a task that is quite different, but it's a pretty good bet that the techniques used for plug in architectures can be applied here.

        Something to think about is either requiring your users to use a common interface or even to derive their code from a common base class you provide. On the face of it your problem would be solved if your users bend a little, or even if you write shims around their code, so that your engine doesn't become a maintenance nightmare.

        Premature optimization is the root of all job security
        some users will need different functionality from others, and I just want to "require" & call the appropriate bits.

        Perhaps a better, easier to maintain, approach would be to put the common parts in to a module. Then write function specific programs that use (or require) the common module.

        If function modules already exist, then each function-specific program would just use (or require) whichever function module (or modules) is (are) needed, as well as the common module.

Re: Call sub in variable module
by BrowserUk (Patriarch) on Nov 07, 2016 at 01:42 UTC

    Try this:

    { package Fred123; sub xyz{ print "xyz() called from package ", __PACK +AGE__; }; };; { package Fred456; sub xyz{ print "xyz() called from package ", __PACK +AGE__; }; };; *{ "Fred${_}::xyz" }->() for 123, 456;; xyz() called from package Fred123 xyz() called from package Fred456

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Good answer, BrowserUk!
      Concise & cryptic, but effective...and it even works!
      Thanks for your response and keep up the good work.
      BTW, if you happen to know where I can read up about that *{ ... } syntax, please let me know.
      tel2
        BTW, if you happen to know where I can read up about that *{ ... } syntax, please let me know.

        Um. I'm not sure that I've ever seen any documentation for that particular construct.

        It is alluded to here, though if start here and move forward that might make more sense, but its pretty sparse.

        And if you read between the lines of that and the section of perlref on Symbolic References you'll get most of the gist.

        I you want my take on explaining it, yell and I'll try to work something up tomorrow.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Call sub in variable module
by kcott (Archbishop) on Nov 07, 2016 at 01:16 UTC

    G'day tel2,

    The documentation for require explains how to achieve this. See the text, about half-way down, near:

    eval "require $class";

    Update: Sorry, I appear to have missed the last line of your post:

    "Also, if each module will always contain only 1 sub, do they need to have a sub at all? If not, how can they be written & called without a sub?"

    That's not addressed in the require documentation.

    Actually, I don't understand what you're asking here which appears to be "How to call a sub that doesn't exist?". Please elaborate.

    — Ken

      Thanks Ken,

      I have recently read that area of that "require" webpage, but I couldn't see anything which answered my question, i.e. "how can I call mysub() now?", and I still can't now.
      Could you please copy/paste the exact sentence that answers that question?

      Regarding the 2nd part of my question, i.e.:
      "Also, if each module will always contain only 1 sub, do they need to have a sub at all? If not, how can they be written & called without a sub?"
      , I was just about to remove it from my original question when you (with lightning speed which proves you must be just across the ditch, mate) responded.  I've removed it now, because it's not really related, and might ask it again as a separate question someday.  Meanwhile, let's (virtually) sweep that one under the carpet.

      Thanks.

        Once you've done the

        eval "require $class";

        part, you just need

        $class->mysub();

        to call it. Here's a working example.

        Module './pm_1175392/mymod123.pm':

        package pm_1175392::mymod123; sub mysub { return 'In package: ' . __PACKAGE__; } 1;

        Script './pm_1175392_variable_name_mod.pl':

        #!/usr/bin/env perl -l use strict; use warnings; my $modno = '123'; my $class = "pm_1175392::mymod$modno"; eval "require $class"; print $class->mysub();

        Sample run:

        $ ./pm_1175392_variable_name_mod.pl In package: pm_1175392::mymod123 $

        The require documentation has information on the eval part. See "perlobj: Invoking Class Methods" for information on the calling part.

        Regarding the bit now "under the carpet", please don't do that. It's better to <strike> such text so that subsequent posts still make sense (all explained here). And, yes, I am "just across the ditch" :-)

        — Ken

Re: Call sub in variable module
by RonW (Parson) on Nov 07, 2016 at 22:21 UTC
    Also, if each module will always contain only 1 sub, do they need to have a sub at all? If not, how can they be written & called without a sub?

    While I see you struck out this question, I can give you an explanation anyway.

    That depends on whether you are calling the subroutine more than once.

    If you are only calling the subroutine once, then you could skip defining a sub in the file. HOWEVER, any parameters you need to pass to the code in the file would have to be placed in global variables.

    Note that repeating a require of a given file will not re-execute the code in it, no matter how many times you require that same file. It only get executed the first time you require a given file. (Though, of course, each different file required will be executed the first time each is required.)

    In general, it's better to define subroutines that you call with the needed parameters. Even if the sub is only ever called once. This is cleaner and easier to understand and maintain.

    Note: There is a way to "load and execute" the contents of a file any number of times. This can be done with do. HOWEVER, every time you do a file, it will be re-read and re-parsed. Also, unlike require, do only accepts a pathname to the file. Also, like require, any parameters that need to be passed will have to be put in variables.

    I strongly suggest you continue to define subroutines that get called instead of trying to "call" a file (or module).

      OK, thanks Ron.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (2)
As of 2024-04-26 06:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found