Solved

Subroutine library calls in Perl

Posted on 2003-11-20
7
766 Views
Last Modified: 2013-12-25
In Perl, I have created a file containing several shared subroutines ("subrout.lib") and then including the command "require 'subrout.lib';" in each script that references one or more of the subroutines.  That works well except when a script calls itself (for instance, to replot the screen with the data sorted differently).  It clearly accesses the subroutines the first time, but does not access them in subsequent calls.

When I include the shared subroutines in each script, everything works fine.  That obviously increases the size of my scripts and is no fun to maintain.  Before I proceed, I thought I would ask what is the best way to (a) set up a library of subroutines and (b) call a subroutine from that library.
0
Comment
Question by:ryuuseki
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 5

Assisted Solution

by:djplaistow
djplaistow earned 50 total points
ID: 9791156
For a package named DBUtilities, which by convention would be stored in a file named DBUtilities.pm, the begining would look like:

    package DBUtilities;

    require Exporter;
    @ISA = qw(Exporter);
    @EXPORT = (SqlFunction AnotherFunc); # List all subroutines and variables that will be automatically
                                                                   # exported to all scripts that use the module
    @EXPORT_OK = qw(Func1 $globalDsn  @tables); # List all subroutines and variables that will be exported
                                                                                  # to all scripts that explicitly name them

Then a script that wants to use subroutines and/or variables that are within DBUtilities would add a line like:

    use DBUtilities qw(SqlFunction @tables);

Thus, the script will have acces to the subroutines SqlFunction (which it did not have to explicitly request),  and AnotherFunc, and the variable @tables. However, it will not have access to the subroutine Func1 or the variable $globalDsn as it would have had to explicitly request them.
0
 
LVL 5

Assisted Solution

by:djplaistow
djplaistow earned 50 total points
ID: 9791186
I forgot to spell out the answer to "(b) call a subroutine from that library." Once you have included the line like:

    use DBUtilities qw(SqlFunction @tables);

You treat it as if the code for the function is within the script itself; it is analogous to the C++ using namespace construct.
0
 
LVL 84

Assisted Solution

by:ozo
ozo earned 25 total points
ID: 9791726
How does it fail when a script calls itself?
Could you give an example of code that does not work the way you think it should?
0
PowerShell Core for Advanced Linux Administrators

Understand advanced principals around Powershell Core with a focus on the Linux Administrator.  This course covers how to administer numerous environments across multiple platforms including Linux, Azure, AWS, and Google Cloud from a single shell instance.

 
LVL 51

Assisted Solution

by:ahoffmann
ahoffmann earned 25 total points
ID: 9800243
before converting to packages, could you please post the require and the exec (itself) part of your script
0
 

Author Comment

by:ryuuseki
ID: 9819929
I appreciate the comments.  Honestly, I was hoping there would be a simpler answer than working with packages.

In theory, should the calls using require work?  Is there any inherent problem with this method?  The scripts are on our internal server, and too large to post in this forum.  I can try to write a smaller script that replicates the failure, but I'd rather put my efforts toward proper technique if this method is not recommended.
0
 

Author Comment

by:ryuuseki
ID: 9820690
*sigh*  Just when I think I understood something, I realize I really didn't.

The failure appears to be related to the scoping of "my" variables.  I have always used strict scoping with "my" variables.  What I didn't quite understand was the concept of packaged scoping of the "my" vars.

Simply put, in the following example, $v2 is visible to the subroutine "test":

(main.pl)
use strict;
my($v1) = "VAR 1";
my($v2) = "VAR 2";
print "$v1\n";
print "$v2\n";
&test();

sub test {
  print "$v2\n"; }

If I change it to the following, $v2 is not visible to "test":

(main.pl)
use strict;
require "subrout.lib";
my($v1) = "VAR 1";
my($v2) = "VAR 2";
print "$v1\n";
print "$v2\n";
&test();

(subrout.lib)
sub test {
  print "$v2\n"; }

1;

By changing "my($v2)" to "our($v2)" it becomes visible outside of the "main" package.

I'm still not sure why the complicated script works the first time through but not on subsequent calls.  I'll have to dig deeper to figure that out.


In the meantime, I'd still appreciate comment regarding my previous comment re: the propriety of using require.
0
 
LVL 3

Accepted Solution

by:
rkosai earned 25 total points
ID: 9827046
To allieviate problems such as these, as well as making code easier to read (and following "better" coding practices), it is usually recommended to make each of your subroutines isolated from each other.  This avoids many problems, including ones like this.

So, alternatively, you'd write code like this.

use strict;
require "subrout.lib";
my $v1 = "VAR 1";
my $v2 = "VAR 2";
print "$v1\n";
print "$v2\n";
test($v2); #prints $v2

# -- (subrout.lib) --
sub test {
  shift; #captures the arguments to the subroutine, and stores them in $_
  print "$_\n"; }

1;
0

Featured Post

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This tutorial will give you a fast look what you can do with WhizBase. I expect you already know how to work with HTML at least, and that you understand the basics of the internet and how the internet works. WhizBase is a server-s…
Batch, VBS, and scripts in general are incredibly useful for repetitive tasks.  Some tasks can take a while to complete and it can be annoying to check back only to discover that your script finished 5 minutes ago.  Some scripts may complete nearly …
Learn the basics of modules and packages in Python. Every Python file is a module, ending in the suffix: .py: Modules are a collection of functions and variables.: Packages are a collection of modules.: Module functions and variables are accessed us…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

617 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question