http://qs1969.pair.com?node_id=619554

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

This is probably a stupid beginners question but one has to begin somewhere...

I have a perl file that contains a whole bunch of subroutines. I have a set of different perl scripts that would reuse the subroutines so that I do not have to copy paste the routines all the time.

An important question I have regarding this is that when above is possible, are the variables then known in the load shared library.

Example:
mainscript.pl
$hello="hello123"; &hello;


routines.pl contains
sub hello { print $hello; }

Replies are listed 'Best First'.
Re: Include subs from different perl file
by Ovid (Cardinal) on Jun 06, 2007 at 08:58 UTC
Re: Include subs from different perl file
by almut (Canon) on Jun 06, 2007 at 09:34 UTC

    In the most simple case, you could just include the file using require. Unless you tell Perl otherwise (using a package ... declaration), everything will end up in the same namespace (i.e. main::). So yes, the variable $hello will be known within the included routine.

    routines.pl

    sub hello { print $hello; } 1; # need to end with a true value

    mainscript.pl

    #!/usr/bin/perl require "./routines.pl"; # assuming it's in the current directory $hello="hello123"; hello(); # prints "hello123"

    Having said that, do use modules instead (with their own separate namespaces) for anything larger. This will help keep the mess to a minimum, which would otherwise ensue when the code grows... Same holds for global variables (like your $hello), so try to make judicious use of them...   In other words, you'd more typically pass $hello as an argument to the function, e.g.

    sub hello { my $hello_msg = shift; print $hello_msg; } # ... $hello="hello123"; hello($hello); # or just: # hello("hello123");
Re: Include subs from different perl file
by Moron (Curate) on Jun 06, 2007 at 09:23 UTC
    In the first place, you don't have a shared library. A shared library is an object language file that was compiled independently of your code and needs a special module e.g. P5NCI::Library to make it available to Perl (update: without writing unix hacker-level glue code yourself that is to say).

    In the second place you also don't have a module - see perlmod for how to construct the Perl equivalent of a shared library. I presume you are loading the non-module routines.pl using require - that is really the Perl equivalent of a #INCLUDE in C.

    The short answer to the question is "yes" because $hello is global BUT you don't really want to rely on global variables because then you make your "library" dependent on what is defined as global for particular main routines - that's not good code design. Better is to pass parameters to your "shared" subroutines, e.g.:

    #!/usr/bin/perl # main program; use strict; use warnings; use Routines;; { # closure to avoid global variables my $hello = "hello123; # ... hello( $hello ); } __END__ # Routines.pm - a separate file called a "module" package Routines; sub hello { my $hello = shift; print "$hello\n"; } 1;
    __________________________________________________________________________________

    ^M Free your mind!

    .

Re: Include subs from different perl file
by TGI (Parson) on Jun 06, 2007 at 19:39 UTC

    Code reuse is a wonderful thing. You are getting great advice here. Use modules (see perlmod) and avoid globals, pass data to subs as arguments.

    If you must use globals, you can either use package globals or import your variables so that you can see them in your main script. I'll show you how to specify the package of variables and subroutines here. Exporting/importing symbols is a bit more complex, so I'll leave that to the proper documentation.

    File Foo.pm:

    package Foo; my $hello; sub hello { print "$hello\n"; return; # I like explicit returns. }

    File myscript.pl:

    use strict; use warnings; use Foo; $Foo::hello = 'hello'; Foo::hello(); #prints "hello\n"

    Also, ditch the unneeded & sigil from your subroutine calls. It can have unexpected consequences. Here are the relevent bits from perlsub, with emphasis added:

    ...If a subroutine is called using the & form, the argument list is optional, and if omitted, no @_ array is set up for the subroutine: the @_ array at the time of the call is visible to subroutine instead. This is an efficiency mechanism that new users may wish to avoid.
    ...
    Not only does the & form make the argument list optional, it also disables any prototype checking on arguments you do provide. This is partly for historical reasons, and partly for having a convenient way to cheat if you know what you're doing. See Prototypes below.

    See perlsub for more details.

    I think I need to put together a meditation - Ampersand Considered Harmful...


    TGI says moo

      Well, on modern Perl incarnations, I have to do:
      our $hello;
      instead of
      my $hello;
      It will not print the string in that variable, if I use my. Otherwise, thanks. Yet another soul got a door opened to Perl Modules.
Re: Include subs from different perl file
by perllove (Beadle) on Jun 07, 2007 at 04:24 UTC
    As the philosophy of perl goes you have several ways to do this.

    1. Compile the code into module and call it using 'use' then you can use the name of the subroutine as just its in your code.

    2. One more way than using the use statement is to include it in the @INC array, with the following syntax push "scriptname.pl", @INC

    3. one more simple way to do is to use include or require statement