http://qs321.pair.com?node_id=245294

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

Is there a way to RUN a function (or sub) in another file DYNAMICALLY (eg. on-the-run?). How is this done?
  • Comment on Loading a function from another file dynamically?!

Replies are listed 'Best First'.
Re: Loading a function from another file dynamically?!
by gmax (Abbot) on Mar 23, 2003 at 19:07 UTC

    Using a module, you can run a function defined in that module. The module must be loaded at compile time.

    However, Perl allows you to define subs in other files and load them in several ways. I'll show you some.

    Here's the main file

    #!/usr/bin/perl -w use strict; my $method = shift || 1; my $filename = shift || 'other.pl'; my $sub = shift || 'hello'; if ($method == 1) { print "First method\n"; { local $/; open OTHER, "< $filename" or die "can't open\n"; my $other = <OTHER>; close OTHER; eval $other . ";$sub"; } } elsif ($method == 2) { print "Second method\n"; scalar eval `cat $filename`; eval $sub; } else { print "Third method\n"; do $filename; eval $sub; }

    In this file we define one sub.

    #cat other.pl sub hello { print "hello world\n"; }

    And one more in this other file.

    # cat other2.pl sub hi { print "hi, world!\n"; }

    As an example, you can run this script

    $ perl test_runtime.pl 1 other.pl hello

    Where "1" is the method to use, "other.pl" is the file containing your function, "hello" is the function name.

    Try also

    $ perl test_runtime.pl 2 other2.pl hi $ perl test_runtime.pl 3 other2.pl hi

    And see for yourself what happens.

    CAVEAT. Using eval you are compiling and running code at run time. When you run a normal script, the Perl compiler will catch the mistakes and inform you about them. With eval, you should catch the errors by checking eval's return value. See the docs for more info.

    _ _ _ _ (_|| | |(_|>< _|
      Using a module, you can run a function defined in that module. The module must be loaded at compile time.

      Partly true. More accurately, you can cause perl to compile things at run-time. The important bit is that it knows how to do the thing you're going to ask it to do when you ask to do it. require, in this case, can be quite useful.

      thanks. that worked well :).. I think I'll just use number 3 since it's the shortest. eval() return values aren't that important to me, since it's only for my wwwsite. There aren't any real differences between these methods, are there?

        The first method loads the file into a string, then evals it.

        The second method uses an external program (cat) to read the file, taking up a bit more resources.

        The third method is the "preferred" way of doing it, but has a couple of differences: the file is looked for in all the directories listed in the @INC array; the code in the file will not be able to access lexical variables declared (with my) in the scope in which the do is executed. (for details, perldoc -f do).

        -- 
                dakkar - Mobilis in mobile
        
Re: Loading a function from another file dynamically?!
by The Mad Hatter (Priest) on Mar 23, 2003 at 18:41 UTC
    If I understand the question correctly, you'd like to be able to run sub A in file A from file B. To do this, you can use Exporter:

    File A

    package PackageName; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(moo); # Put function names, seperated by + spaces, # that you want to be able to use sub moo { # do stuff }

    File B

    use PackageName; moo();

    Basically, you're creating a simple module. You'd also be able to accomplish what you want it via eval, but modules are cleaner.

      not exactly. I wrote a parser that parses SSI -like tags and would like to able to specify:
      A) the source file to load
      B) the name of the sub to run
      C) the args used
      
      and now I am trying to figure out the code for running the function in the file specified etc. I guess it has something to do with evals and packages... but I know too little Perl for figuring it out, and no manual has anything on this.

      Edit by tye, remove PRE tags around long lines