Solved

Subroutine library calls in Perl

Posted on 2003-11-20
7
756 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
Guide to Performance: Optimization & Monitoring

Nowadays, monitoring is a mixture of tools, systems, and codes—making it a very complex process. And with this complexity, comes variables for failure. Get DZone’s new Guide to Performance to learn how to proactively find these variables and solve them before a disruption occurs.

 
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

How our DevOps Teams Maximize Uptime

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us. Read the use case whitepaper.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Recursively Delete Files 5 110
powershell md/mkdir/New-item   -Quiet 10 373
Review of the nodejs code 1 56
Automate PC's, Laptop to correct OU 4 52
In this tutorial I will focus on how to use WhizBase as a tool for sending ICQ messages to ICQ. Here I will use a new technology in WhizBase, published in WhizBase 5.1 version. In this tutorial I will use 3 files, pager.wbsp for the processing, e…
A quick Powershell script I wrote to find old program installations and check versions of a specific file across the network.
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…
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…

738 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