0

I would like to set up a dedicated package for all common declarations to main perl program and other packages as well, without repeating these declarations in every headers. I get it wrong for sure but could not figure out the rationals behind that :

Let's assume :
- I have setup my common data within the package my_common_declarations.pm.
- I want to use these data within another package, my_perl_utils.pm for example.

#!/usr/bin/perl -w
package my_perl_utils;
use parent qw(Exporter);
our @EXPORT_OK = qw(f1 f2);
use my_common_declarations qw(debugme);
my %setup = &debugme;
my $DEBUGME = $setup{setup}{debugme};

# This generates this error : "Use of uninitialized value"
use constant true => $setup{setup}{'true'};
print "=" x25, "\nDEBUG true :\nimport = " . $setup{setup}{'true'} . "\nconstant = " , true , "\n", "=" x25, "\n"; 

sub f1{
# some rationals using the true or false constants
}

sub f2{
}

1;  

I can't succeed in getting the 'true' constant declared without errors.

Shall I import the common declarations package only once in the main program and declare the constant accordingly in there, or redeclare it within each package where I need this constant ?

thx

hornetbzz
  • 9,188
  • 5
  • 36
  • 53

1 Answers1

6

The problem you are running into is the interaction between runtime and compile time in your script. Any use declaration has an implicit BEGIN {...} block around it, which means that it takes place at compile time. Your assignment to %setup happens at runtime, after the constant has been declared. The fix for this is to declare the variable, and then perform the assignment to it in a BEGIN block. That way, the variable will be defined by the time use constant ... is called:

use my_common_declarations 'debugme';

my (%setup, $DEBUGME);  # declare variables with file scope

BEGIN {
    %setup   = debugme;                # assign to variables at compile time
    $DEBUGME = $setup{setup}{debugme};
}

use constant true => $setup{setup}{true}; # %setup is defined now

Alternatively, since you are exporting a function that returns a hash, why not have it return a hash reference, then you could write your code as:

use my_common_declarations 'debugme';

use constant true => debugme->{setup}{true};

In that case, since debugme is imported by the first use statement at compile time, it is available in the use constant ... line.

But since you are declaring a package for common declarations, why not just move the definition of your constants into that package, and then add things like true to the export list for that package?

Eric Strom
  • 39,821
  • 2
  • 80
  • 152
  • thx I'll look carefully to your comments and try to implement. – hornetbzz Apr 05 '11 at 15:40
  • 1
    But he's also using an underscore in the package name, which means it's reserved for local use (just like he's doing). See [this question](http://stackoverflow.com/questions/658955/how-do-i-choose-a-package-name-for-a-custom-perl-module-that-does-not-collide) for details. – cjm Apr 05 '11 at 15:50
  • @cjm => Thanks for pointing that out, I have removed that portion of my answer. – Eric Strom Apr 05 '11 at 15:54
  • I did move the definition of the constants into the package as adviced, much better, many thx. Also [this](http://stackoverflow.com/questions/193020/how-do-i-use-constants-from-a-perl-module) helped. – hornetbzz Apr 06 '11 at 09:39