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

    From Henry Law@21:1/5 to All on Thu Nov 5 23:22:56 2020
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rainer Weikusat@21:1/5 to Henry Law on Fri Nov 6 16:04:56 2020
    Henry Law <news@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).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rainer Weikusat@21:1/5 to Rainer Weikusat on Fri Nov 6 16:45:23 2020
    Rainer Weikusat <rweikusat@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Henry Law@21:1/5 to Rainer Weikusat on Fri Nov 6 10:38:16 2020
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eric Pozharski@21:1/5 to Henry Law on Sat Nov 7 16:28:34 2020
    with <aa4285b7-4a0a-4a51-a13f-1682ed8ceb56n@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)