Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Subroutine library calls in Perl

Posted on 2003-11-20
7
Medium Priority
?
771 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 100 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 100 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 50 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
How To Reduce Deployment Times With Pre-Baked AMIs

Even if we can't include all the files in the base image, we can sometimes include some of the larger files that we would otherwise have to download, and we can also sometimes remove the most time-consuming steps. This can help a lot with reducing deployment times.

 
LVL 51

Assisted Solution

by:ahoffmann
ahoffmann earned 50 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 50 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

Give Your Engineering Team a Productivity Boost

Learn why container technology is so powerful and how it can provide your team with productivity gains and other benefits.

Question has a verified solution.

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

Making a simple AJAX shopping cart Couple years ago I made my first shopping cart, I used iframe and JavaScript, it was very good at that time, there were no sessions or AJAX, I used cookies on clients machine. Today we have more advanced techno…
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 …
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

670 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