sql-noob
sql-noob

Reputation: 423

Importing sub into perl module package

Coming from Python and Java background this is confusing me a bit. I have the following files:

Constants.pm

Utils.pl

Main.pl

Constants.pm has global variables that I'd like to share with Main.pl and Utils.pl.

Utils.pl has helper subs that I'd like to share with Constants.pm and Main.pl

#################### Constants.pm
package Constants;
require "Utils.pl";
use Exporter;
our @ISA = 'Exporter';

my %config = parseConfigFile("File.properties");

our @EXPORT = qw($var1 $var2 $var3);
our ($var1, $var2, $var3);

$var1 = $config{var1};
$var2 = $config{var2};
$var3 = $config{var3};


#################### Utils.pl
package Utils;
use Constants;

sub parseConfigFile {};
sub someSub {};

#################### Main.pl
use Constants;
require "Utils.pl"

my $var = someSub($var1);

When I run Main.pl I'm getting someSub is undefined error

Please help, thanks!

EDIT: I haven't tried @ikegami's answer instead I just moved everything in Constants into Utils.pm and importing Utils by using 'use' in main.pl

Upvotes: 0

Views: 125

Answers (1)

ikegami
ikegami

Reputation: 386591

[The following explanation applies to the original version of the question. The solution is the same.]

require only executes a file once, but you expect the identical subs to be present in two packages. The simple solution is to use do instead of require. But then you end up with a poor design. You end up with multiple instances of the variables and subs created by Utils.pl. It's much better to convert Utils.pl into a proper module (like Constants.pm).

Constants.pm:

package Constants;

use strict;
use warnings;

use Exporter qw( import );
use Utils    qw( parseConfigFile );

our @EXPORT_OK = qw( $var1 $var2 $var3 );

my %config = parseConfigFile("File.properties");
our $var1 = $config{var1};
our $var2 = $config{var2};
our $var3 = $config{var3};

1;

Utils.pm:

package Utils;

use strict;
use warnings;

use Constants qw( ... );
use Exporter  qw( import );

our @EXPORT_OK = qw( parseConfigFile someSub );

sub parseConfigFile { ... }
sub someSub { ... }

1;

main.pl:

#!/usr/bin/perl

use strict;
use warnings;

use Constants qw( $var1 );
use Utils     qw( someSub );

my $var = someSub($var1);

But oops! Constants uses Utils, and Utils uses Constants, and they both import from the other. That's a problem. You can work around it, but there's no reason for parseConfigFile to be in Utils, so let's just avoid the problem entirely.

Constants.pm:

package Constants;

use strict;
use warnings;

use Exporter qw( import );

our @EXPORT_OK = qw( $var1 $var2 $var3 );

sub parseConfigFile { ... }

my %config = parseConfigFile("File.properties");
our $var1 = $config{var1};
our $var2 = $config{var2};
our $var3 = $config{var3};

1;

Utils.pm:

package Utils;

use strict;
use warnings;

use Constants qw( ... );
use Exporter  qw( import );

our @EXPORT_OK = qw( someSub );

sub someSub { ... }

1;

(I use @EXPORT_OK instead of @EXPORT because I believe it's a good idea to explicitly name your imports.)

Upvotes: 1

Related Questions