Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to pass parameters to my module when "use"-ing it

16 views
Skip to first unread message

Henry Law

unread,
Nov 5, 2020, 6:23:02 PM11/5/20
to
I have a Perl module which is included in numerous programs in the suite
I'm writing. I need to vary the way in which the module is imported (to
do with whether it's to fail or not if certain resources aren't
available), so I want to be able to code

use MyPackage; # When it's to check that the resources are available
use MyPackage nocheck=>1; # When it's not to check

I have written an "import" method in the module which interrogates the
parameters (nocheck=>1 in the example); once that's done I need
Exporter's import method to continue to do its thing with exporting
subroutines and so forth.

I've got it wrong: the @EXPORT array is ignored, and subroutines which
should have been exported by it are unknown by the calling program.
Here are my test module and the program that uses it; can someone tell
me how to make it do what I want?

# ------- MyPackage.pm
package MyPackage;
use strict;
use warnings;
use 5.014;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw/afunction/;

sub import{
my $package_name = shift;
my %parms;
if ( @_ && !(@_ % 2) ){ # Check for even number
%parms = @_;
}
printf "MyPackage::import [parms: %s] invoking Exporter::import %s\n",
(scalar keys %parms), $package_name;
Exporter::import $package_name;
}

sub afunction{
print "This is function afunction\n";
}

1;

# -------- UseMyPackage
#!/usr/bin/perl

use strict;
use warnings;
use 5.014;

use FindBin qw( $Bin );
use lib $Bin;

use MyPackage foo=>'This is foo';
afunction();

---- when I run it -----
./UseMyPackage
MyPackage::import [parms: 1] invoking Exporter::import MyPackage
Undefined subroutine &main::afunction called at ./UseMyPackage line 12.

--
Henry Law n e w s @ l a w s h o u s e . o r g
Manchester, England

Rainer Weikusat

unread,
Nov 6, 2020, 11:05:04 AM11/6/20
to
Henry Law <ne...@lawshouse.org> writes:

> I have a Perl module which is included in numerous programs in the
> suite I'm writing. I need to vary the way in which the module is
> imported (to do with whether it's to fail or not if certain resources
> aren't available), so I want to be able to code
>
> use MyPackage; # When it's to check that the resources are available
> use MyPackage nocheck=>1; # When it's not to check
>
> I have written an "import" method in the module which interrogates the
> parameters (nocheck=>1 in the example); once that's done I need
> Exporter's import method to continue to do its thing with exporting
> subroutines and so forth.

[...]

> # ------- MyPackage.pm
> package MyPackage;
> use strict;
> use warnings;
> use 5.014;
>
> require Exporter;
> our @ISA = qw(Exporter);
> our @EXPORT = qw/afunction/;
>
> sub import{
> my $package_name = shift;
> my %parms;
> if ( @_ && !(@_ % 2) ){ # Check for even number
> %parms = @_;
> }
> printf "MyPackage::import [parms: %s] invoking Exporter::import %s\n",
> (scalar keys %parms), $package_name;
> Exporter::import $package_name;
> }

The Exporter import exports symbols into the namespace of the calling
package. In your case, that's MyPackage, hence, it's trying to export
the symbol into the package which defines it (symbol is really a Lisp
term and not a Perl term, but ... oh well ...). You have to use goto to
call the subroutine to make the intermediate activation record go
away:

-----------
package MyPackage;
use strict;
use warnings;
use 5.014;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw/afunction/;

sub import{
my $package_name = shift;
my %parms;
if ( @_ && !(@_ % 2) ){ # Check for even number
%parms = @_;
}
printf "MyPackage::import [parms: %s] invoking Exporter::import %s\n",
(scalar keys %parms), $package_name;
@_ = ($package_name);
goto &Exporter::import
}

sub afunction{
print "This is function afunction\n";
}

1;
-------------

(tested with 5.24.1).

Rainer Weikusat

unread,
Nov 6, 2020, 11:45:29 AM11/6/20
to
Rainer Weikusat <rwei...@talktalk.net> writes:

[...]

> @_ = ($package_name);

This pair of brackets is not needed: Assigning a scalar value to an
array has the same effect as assigning a single-item list to it.

Henry Law

unread,
Nov 6, 2020, 1:38:22 PM11/6/20
to
On Friday, 6 November 2020 at 16:05:04 UTC, Rainer Weikusat wrote:
> The Exporter import exports symbols into the namespace of the calling
> package. In your case, that's MyPackage, hence, it's trying to export
> the symbol into the package which defines it (symbol is really a Lisp
> term and not a Perl term, but ... oh well ...). You have to use goto to
> call the subroutine to make the intermediate activation record go
> away:

Excellent; thank you. I ran my test programs under the debugger and, now that you've explained it, I can understand what I saw happening there.

A GOTO statement ... how exciting! I don't think I've coded one of those since I wrote some BASIC for a 512Kb DOS PC.

Eric Pozharski

unread,
Nov 7, 2020, 1:33:17 PM11/7/20
to
with <aa4285b7-4a0a-4a51...@googlegroups.com> Henry Law wrote:
> On Friday, 6 November 2020 at 16:05:04 UTC, Rainer Weikusat wrote:

>> The Exporter import exports symbols into the namespace of the calling
>> package. In your case, that's MyPackage, hence, it's trying to export
>> the symbol into the package which defines it (symbol is really a Lisp
>> term and not a Perl term, but ... oh well ...). You have to use goto
>> to call the subroutine to make the intermediate activation record go
>> away:
> Excellent; thank you. I ran my test programs under the debugger and,
> now that you've explained it, I can understand what I saw happening
> there.

I'm no way expert of Exporter (%EXPORT_TAGS is enough for me), but
reading its perldoc suggests 'export_to_level'. However, 'goto' will be
just as fine.

*CUT*

--
Torvalds' goal for Linux is very simple: World Domination
Stallman's goal for GNU is even simpler: Freedom
0 new messages