Alternative to Export for constants

K

kj

One thing that bugs me about the Export module is that even when
you want the module to export everything, one still has to register
things in @EXPORT. I find it particularly annoying in cases when
I have a module that contains only constants to be shared by other
modules and scripts, like this:

# file My_Constants.pm
package My_Constants;
use base 'Exporter';
our @EXPORT = qw(FOO BAR ... );
use constant FOO => 1;
use constant BAR => 4;
# etc.
1;

# file some_script.pl
use My_Constants;

printf "%d %d\n", FOO, BAR;



Instead, I think I would prefer to do something like this:



# file My_Constants.pm
package My_Constants;
use constant FOO => 1;
use constant BAR => 4;
# etc.
1;

# file some_script.pl
use My_Constants;

our $Const = bless \{ my $c }, 'My_Constants';

printf "%d %d\n", $Const->FOO, $Const->BAR;



It works, though I've never thing anything like this done. Is
there anything particularly wrong with it?

Thanks,

kj
 
B

Ben Morrow

kj said:
One thing that bugs me about the Export module is that even when ^^ er
you want the module to export everything, one still has to register
things in @EXPORT. I find it particularly annoying in cases when
I have a module that contains only constants to be shared by other
modules and scripts, like this:

# file My_Constants.pm
package My_Constants;
use base 'Exporter';
our @EXPORT = qw(FOO BAR ... );
use constant FOO => 1;
use constant BAR => 4;
# etc.
1;
# file My_Constants.pm
package My_Constants;
use constant FOO => 1;
use constant BAR => 4;
# etc.
1;

# file some_script.pl
use My_Constants;

our $Const = bless \{ my $c }, 'My_Constants';

printf "%d %d\n", $Const->FOO, $Const->BAR;

It works, though I've never thing anything like this done. Is
there anything particularly wrong with it?

You won't get constant inlining, and the interface is messy (do you
really want to have to do that 'bless' every time you use the module?)

A better answer is something like

package My_Constants;

use constant;
use base qw/Exporter/;

my %consts = (
FOO => 1,
BAR => 2,
);

our @EXPORT = keys %consts;
for (keys %consts) {
import constant $_ => $consts{$_};
}

1;

Ben
 
B

Ben Morrow

Another, stronger, objection is that this comes under the heading
'using the symbol table when you could use an ordinary hash' (method
calls are, essentially, symrefs).

package My_Constant;

use base qw/Exporter/;
our @EXPORT = qw/%Consts/;

out %Consts = (
FOO => 1,
BAR => 2,
);

1;

package main;

use My_Constant;

print $Const{FOO}, $Const{BAR};

Ben
 
J

Jay Tilton

: One thing that bugs me about the Export module is that even when
: you want the module to export everything, one still has to register
: things in @EXPORT. I find it particularly annoying in cases when
: I have a module that contains only constants to be shared by other
: modules and scripts, like this:
:
: # file My_Constants.pm
: package My_Constants;
: use base 'Exporter';
: our @EXPORT = qw(FOO BAR ... );
: use constant FOO => 1;
: use constant BAR => 4;
: # etc.
: 1;

If your complaint is about having to maintain the constants and the
@EXPORT array in parallel, you could do:

my %c;
BEGIN {
%c = (
FOO => 1,
BAR => 4,
);
}
use constant \%c;
use base 'Exporter';
our @EXPORT = keys %c;

: Instead, I think I would prefer to do something like this:
:
: # file My_Constants.pm
: package My_Constants;
: use constant FOO => 1;
: use constant BAR => 4;
: # etc.
: 1;
:
: # file some_script.pl
: use My_Constants;
:
: our $Const = bless \{ my $c }, 'My_Constants';
^^^^^^^^^^
What's that "my $c" thing in the anonymous hash supposed to be?

Why are you taking a reference to that anonymous hash?

You don't need to bless anything. Just " $Const = 'My_Constants'; "
will work just fine for what you're doing.

: printf "%d %d\n", $Const->FOO, $Const->BAR;
:
: It works, though I've never thing anything like this done. Is
: there anything particularly wrong with it?

Nothing really wrong with it, except it's rather noisy.

Does prefacing every constant name with "$Const->" really save work over
setting up the module to export them?

Does writing "$Const->FOO" give significant benefit over writing
"My_Constants::FOO" ? I can see it being useful for swapping out one
set of constants for another by changing the value in $Const, but I
can't see needing that capability very often.
 
K

kj

A

Anno Siegel

Ben Morrow said:
You won't get constant inlining, and the interface is messy (do you
really want to have to do that 'bless' every time you use the module?)

The "bless" is a red herring. Instead of generating an irrelevant object
to call the constant through, it can be called directly as a class method:

My_Constants->FOO;

It's clearly not quite clean. The constant will be called with an argument,
(class or object, either way), which its prototype actually forbids. It
only works because prototypes are ignored in method calls. Further, there
is no advantage in the class method call over the fully qualified
"My_Constants::FOO". If inheritance is intended, I'd urgently recommend
not using constants but writing standard methods.

[snip good exporting alternative]

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top