james28909 has asked for the wisdom of the Perl Monks concerning the following question:

This is the script i call My::Package functions from:

use strict; use warnings; use My::Package (keys %My::Package::); # <-----why does this work? open (my $file, '<', shift); print_lines($file); test("hello world\n"); test_2("hello this is dog");

And this is my module I created for testing:

package My::Package; use Exporter qw(import); @EXPORT_OK = (keys %My::Package::); use strict; use warnings; sub print_lines{ my ($input) = shift; while(<$input>){ print; } close($input); } sub test{ my ($input) = shift; print $input; } sub test_2{ my ($input) = shift; print $input; }

Sample input data:

this is a test!!!!

I just want to know if this is safe to export with @EXPORT_OK = (keys %My::Package::); and import with use My::Package (keys %My::Package::);.

EDIT: Also am I right in thinking that the reason this works is because I am calling that specific module with keys %My::Package::. If i am wrong please help me understand... more better :)

Replies are listed 'Best First'.
Re: Is this safe to export and import functions this way?
by Corion (Patriarch) on Aug 19, 2015 at 20:30 UTC

    Thanks for posting this!

    One thing that might be a surprising side-effect of your approach is, that it will re-export all functions in the module, even if they were imported themselves already:

    package My::Package; use List::Util 'max'; use Exporter qw(import); @EXPORT_OK = (keys %My::Package::);

    ... will also happily export the max subroutine.

Re: Is this safe to export and import functions this way?
by Laurent_R (Canon) on Aug 19, 2015 at 18:50 UTC
    If I understand it right, you're basically importing the entire symbol table of the My::Package module. IMHO, it is probably not a very good idea, it is probably better to select yourself what you want to import, you might end up with various types of conflicts.
Re: Is this safe to export and import functions this way? (:all)
by tye (Sage) on Aug 19, 2015 at 18:53 UTC

    It won't work the first time you do it because My::Package hasn't been loaded at the time that you try to get the list of keys in order to pass in to the 'use' line. The second time you use it, it might work, but it will still be a really bad idea.

    use My::Package '/./';

    See 'Advanced features' in Exporter.

    - tye        

      Ah, the trick is that the 'use' line becomes:

      BEGIN { require My::Package; My::Package->import( keys %My::Package:: ); }

      so the 'keys' expression is evaluated after the (generated) 'require My::Package;' is run.

      (And I had a typo in my test case.)

      - tye        

      Surprisingly, it works at first launch (I used a simplified version to avoid having to create a file to be read):
      $ perl -e ' use strict; use warnings; use My::Package (keys %My::Package::); # test("hello world\n"); test_2("hello this is dog"); ' hello world hello this is dog
      But I am of course not saying it is a good idea to do that.
Re: Is this safe to export and import functions this way?
by Laurent_R (Canon) on Aug 19, 2015 at 20:12 UTC
    EDIT: Also am I right in thinking that the reason this works is because I am calling that specific module with keys %My::Package::. If i am wrong please help me understand... more better :)
    As a partial answer to this question, I've changed your module as follows:
    # ... use Exporter qw(import); @EXPORT = (keys %My::Package::); # @EXPORT instead of @EXPORT_OK # ...
    And then I can run the test program without specifying the list of symbols to be imported:
    $ perl -e ' use strict; use warnings; use My::Package; test("hello world\n"); test_2("hello this is dog"); ' hello world hello this is dog
    So it seems that the work is really done within the module, which is exporting its symbols.
Re: Is this safe to export and import functions this way?
by james28909 (Deacon) on Aug 19, 2015 at 21:38 UTC
    I didnt know which reply to reply to, so ill just reply to myself haha ;) Anyway, i did change up the module and script a little, to this:
    #Package.pm package My::Package; use strict; #can use strict and warnings as usual now as well without +any warnings use warnings; use Exporter qw(import); our @EXPORT = qw(print_lines test test_2); #just add in function names + as you make them our %EXPORT_TAGS = (all => \@EXPORT); sub print_lines{ my ($input) = shift; while(<$input>){ print; } close($input); } sub test{ my ($input) = shift; print $input; } sub test_2{ my ($input) = shift; print $input; }

    And here is the script calling it

    #script.pl use strict; use warnings; use My::Package qw(:all); open (my $file, '<', shift); print_lines($file); test("hello world\n"); test_2("hello this is dog"); # i love this meme lol

    That ":all" is what i was originally shooting for. Though I also figured out you could just require My::Package; and then just call it in the script with use My::Package; and do not have to specify any functions. Anyways, thanks for the help fellers :)

    UPDATE: Also I wanted to ask, if I use strict and warnings in the main script, is that in the modules scope as well, or do I need to use strict and warnings in the module as well? Also IF strict and warnings are in the same scope, is it just for the functions/subs or the whole module?

      UPDATE: Also I wanted to ask, if I use strict and warnings in the main script, is that in the modules scope as well, or do I need to use strict and warnings in the module as well?

      'use strict' is a pragma that has lexical scope. Loading a module via use loads the module via require which notes "The file is included via the do-FILE mechanism, which is essentially just a variety of eval with the caveat that lexical variables in the invoking script will be invisible to the included code". So a lexical pragma will also not stay in effect.

      So you need to 'use strict;' in each module.

      - tye        

      I suggest doing it this way:

      our @EXPORT_OK = qw(print_lines test test_2); our %EXPORT_TAGS = (all => \@EXPORT_OK);

      Because when you set @EXPORT, the items in @EXPORT are automatically exported.

Re: Is this safe to export and import functions this way?
by locked_user sundialsvc4 (Abbot) on Aug 20, 2015 at 03:50 UTC

    I suppose that it depends upon what you mean by the word, “safe.”   It might work ... yes, it might ... but any change to the module would also affect what it meant, because it does not say what it means.   Instead, it is “clever.”   From a project management point of view, and/or from the point of view of a fellow team-member who might get really tired of being “bit,” no, it is not safe.

    The intent of this construct was clear:   to allow you to list exactly which of the possibly very-many subroutines in the package, you actually intend to use.   It is specifically envisioned to be both descriptive and limiting, and should be used in that fashion.