Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

reusable generic subroutines

Status
Not open for further replies.

williey

Technical User
Jan 21, 2004
242
How do you create generic subroutines that are reusable in different scripts? I tried using "require" but it does not work out.

 
And in your attempt, how did you "try" to require that did not work?
 
This is the main script
Code:
use strict;
use warnings;
use DBI;

#  Subroutine : get_todays_date.pl
#
#  Syntax :    get_todays_date(format_type)  where format_type correlate to the 
#                                            below type code.
#
#  Description: return today's date in various formats.
#               new format can be added when needed.
#
#
# type   format       
# ----   ------
#   1    YYMMDD
#   2    MONTH-DD-YYYY
#       
#
#
#

require "test2.pl";

my $todays_date; 

$todays_date = get_todays_date(1);

print($todays_date);

$todays_date = get_todays_date(1);

print($todays_date);

The subroutine script

Code:
sub get_todays_date 
{
my ($date_format_type) = @_;

my $return_date;

# Date and time definition #

my ($second, $minute, $hour, $day, $month, $year, $weekday, $dayofyear, $isdst)=localtime;
my $yyyy = $year + 1900;
my $yy = substr($yyyy, 2,2);
my $mm = $month;
my $dd = $day;


my @months = ("January",
           "February",
           "March",
           "April",
           "May",
           "June",
           "July",
           "August",
           "September",
           "October",
           "November",
           "December");


if ($mm < 10)
{
  $mm = "0" . $mm;
}

if ($day < 10)
{
  $dd = "0" . $day;
}

if ($date_format_type == 1)
{ 
   $return_date = $yy . $mm . $ dd;
   return $return_date;
}
elsif ($date_format_type == 2)
{
   $return_date = uc(substr($months[$mm - 1], 0, 3)) . "-" . $dd . "-" . $yyyy;
   return $return_date;
}

}
 
Actually this is closely related to what I was about to ask about (and will in a different post). What you want is the Exporter module. Make a separate file named globalFunctions.pm (or whatever.pm), and do the following:

Code:
package globalFunctions;

use Exporter;
@ISA = ('Exporter');

@EXPORT = qw($string @array %hash &function);

$string = "hello, global string.";
@array = (1,2,3,4);
%hash = (
 "A" => "B",
);

sub function {
  print "this is my function that can be used anywhere.";
}

1;

Now, whenever you want to use these scalars, arrays, hashes, or functions, just put "use globalFunctions;" at the top of your script. A few warnings:

a) Make sure Perl knows where to find your globalFunctions.pm file. If you want to put it in your own private directory, put "use lib 'c:/directory/';" at the top of your script so Perl knows to look there. Check out @INC for more on where Perl looks for modules.

b) Make sure the 1; is at the end

c) Don't define the variables as "my" in your globalFunctions file.

d) Put whatever you want to export in the @EXPORT array, otherwise the exporter won't know to ship it out.

Hope that helps,

Nick
 
Thanks for the tips.

Here is my revised code

Code:
#  Subroutine : get_todays_date.pl
#
#  Syntax :    get_todays_date(format_type)  where format_type correlate to the 
#                                            below type code.
#
#  Description: return today's date in various formats.
#               new format can be added when needed.
#
#
# type   format       
# ----   ------
#   1    YYMMDD
#   2    MONTH-DD-YYYY
#       
#
#
#


my $todays_date; 

$todays_date = get_todays_date(1);

print($todays_date);

$todays_date = get_todays_date(1);

print($todays_date);

Code:
package dateFunctions;

use Exporter
@ISA = ('Exporter');

@EXPORT = qw(&get_todays_date);


sub get_todays_date 
{
$date_format_type = @_;

$return_date;

# Date and time definition #

($second, $minute, $hour, $day, $month, $year, $weekday, $dayofyear, $isdst)=localtime;
$yyyy = $year + 1900;
$yy = substr($yyyy, 2,2);
$mm = $month;
$dd = $day;


@months = ("January",
           "February",
           "March",
           "April",
           "May",
           "June",
           "July",
           "August",
           "September",
           "October",
           "November",
           "December");


if ($mm < 10)
{
  $mm = "0" . $mm;
}

if ($day < 10)
{
  $dd = "0" . $day;
}

if ($date_format_type == 1)
{ 
   $return_date = $yy . $mm . $ dd;
   return $return_date;
}
elsif ($date_format_type == 2)
{
   $return_date = uc(substr($months[$mm - 1], 0, 3)) . "-" . $dd . "-" . $yyyy;
   return $return_date;
}

}

1;

when I try to execute the script, it cannot find the function. "Undefined subroutine &main::get_todays_date called at test1.pl line 30.
 
Williey,

You need to have your dateFunctions.pm in a location where Perl can find it, and you need to have "use dateFunctions;" at the top of whatever script wants to use it. That's what I was babbling about with the @INC and use lib 'c:/dir/'; stuff in my earlier post.

-Nick
 
Thanks Nick.

Got it to run after I discover I was missing the ";" after
"use Exporter".

However, the dates returned at incorrect. With the following warning.
"Useless use of a variable in void context at dateFunctions.pm line 13."

Code:
package dateFunctions;

use Exporter;
@ISA = ('Exporter');

@EXPORT = qw(&get_todays_date);


sub get_todays_date 
{
$date_format_type = @_;

$return_date;     <------- line 13

# Date and time definition #

($second, $minute, $hour, $day, $month, $year, $weekday, $dayofyear, $isdst)=localtime;
$yyyy = $year + 1900;
$yy = substr($yyyy, 2,2);
$mm = $month;
$dd = $day;


@months = ("January",
           "February",
           "March",
           "April",
           "May",
           "June",
           "July",
           "August",
           "September",
           "October",
           "November",
           "December");


if ($mm < 10)
{
  $mm = "0" . $mm;
}

if ($day < 10)
{
  $dd = "0" . $day;
}

if ($date_format_type == 1)
{ 
   $return_date = $yy . $mm . $ dd;
   return $return_date;
}
elsif ($date_format_type == 2)
{
   $return_date = uc(substr($months[$mm - 1] , 0, 3)) . "-" . $dd . "-" . $yyyy;
   return $return_date;
}

}

1;
 
willey, this works just fine with require, with a few small changes.

1. The months returned by localtime are numbered 0-11, not 1-12.

2. The file test2.pl must have a 1; as the last line of code. (The file, not the sub.)
Note the bolded changes below:
Code:
sub get_todays_date 
{
my ($date_format_type) = @_;

my $return_date;

# Date and time definition #

my ($second, $minute, $hour, $day, $month, $year, $weekday, $dayofyear, $isdst)=localtime;
my $yyyy = $year + 1900;
my $yy = substr($yyyy, 2,2);
[b]my $mm = $month + 1;[/b]
my $dd = $day;


my @months = ([b]undef,[/b]
           "January",
           "February",
           "March",
           "April",
           "May",
           "June",
           "July",
           "August",
           "September",
           "October",
           "November",
           "December");


if ($mm < 10)
{
  $mm = "0" . $mm;
}

if ($day < 10)
{
  $dd = "0" . $day;
}

if ($date_format_type == 1)
{ 
   $return_date = $yy . $mm . $ dd;
   return $return_date;
}
elsif ($date_format_type == 2)
{
   $return_date = uc(substr($months[[b]$mm[/b]], 0, 3)) . "-" . $dd . "-" . $yyyy;
   return $return_date;
}
} 
[b]1;[/b]
In your main program, add a "\n" at the end of your print statements so everything doesn't print on the same line, i.e.,
Code:
$todays_date = get_todays_date(1);

print($todays_date, [b]"\n"[/b]);

$todays_date = get_todays_date(2);

print($todays_date, [b]"\n"[/b]);
Here's the output:[
040916
SEP-16-2004


This looks like what you intended, no? :)




 
Thanks Mike!
I got it the work with "require". So which is the better method? to use "require" or create a package instead?
 
A big question. I think the documentation covers this more completely than I could hope to. See

perldoc perlmod
perldoc -f use
perldoc -f require


My point was that it wasn't necessary to make it a module in order to get it to work. The problem was caused by minor things in the test2.pl file, not the fact that it wasn't a module. Fix the problems in test2.pl, and it works fine with require.

Modules are certainly "cooler," and they are a sine qua non for Perl OO programming. Require is easier to use. It depends on what you want, and what you need.


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top