Search code examples
perlimportperl-module

Equivalent to: import *


I am creating a Perl equivalent to my Python project.

Description: I have a base module "base.py" that is used by all my scripts via "from base import *" The base module has common subroutines/functions that can be executed inside the scripts

My attempt for Perl was placing inside each script "use base.pm". However the subroutines in Perl were not locally imported to the script so I needed to make a call to the "base" module each time I wanted to execute a subroutine. What is the Perl equivalent to Python's "from base import *"?


Solution

  • A few things:

    • The Local namespace is good to use for your local modules. Perl specifically reserves Local for this purpose. No official module will ever be in the Local namespace.
    • Perl is not Python. Perl will do things a bit differently. Sometimes there's an exact equivalent, sometimes not. This does not have an exact equivalent. Close, but not exact.

    Method #1: Don't Export Any Functions

    All functions you defined in your modules are available if you prefix the full namespace to it. This is the easiest way to define and use functions from your modules and is the least likely to cause problems. It's easy to see where a function came from, and you won't have a problem with two modules using the same function name.

    I have a module called Local::Base that has a single function in it. My program can use this function, by simply referring it as Local::Base::foo:

    My Program

    use strict;
    use warnings;
    use feature qw(say);
    
    use Local::Base;
    
    my $foo_string = Local::Base::foo("string");
    say "Foo: $foo_string";
    

    Local/Base.pm

    package Local::Base;
    
    use strict;
    use warnings;
    
    sub foo {
        my $string = shift;
    
        return qq(I've foo'd "$string"!);
    }
    
    1;
    

    Method #2: Use the Exporter Pragma to Specify What to Automatically Export

    Perl has a special pragma called Exporter that allows me to specify which modules will automatically be imported into my program.

    This is not like Python where I can specify any defined function. Instead, I have to list the ones I want to export. This has a disadvantage over Python's way: In Python, if I write a new function, it's automatically imported without me having to do anything. It also has a big advantage over Python's way: In Python, if I write a new function, it's automatically imported without me having to do anything whether I wanted it imported or not. You can imagine if I wrote a private function I didn't want people to use. In Python, it would automatically be available. In Perl, it wouldn't be unless I specified it:

    My Program

    use strict;
    use warnings;
    use feature qw(say);
    
    use Local::Base;
    
    my $foo_string = foo("string");
    say "Foo: $foo_string";
    

    Local/Base.pm

    package Local::Base;
    use strict;
    use warnings;
    
    use Exporter 'import';
    
    our @EXPORT = qw(foo);
    
    sub foo {
        my $string = shift;
    
        return qq(I've foo'd "$string"!);
    }
    
    1;
    

    Now, whenever I use Local::Base, the foo function is automatically imported.

    Notice that I list all functions I want to export in the @EXPORT array. (Also note I declare that array with an our instead of a my. That our means the @EXPORT is a PACKAGE variable.). Also notice the qw(...) syntax. This is quote word. All words are separate elements of an array. You don't use commas:

    my @array = ("one", "two", "three");
    my @array = qw(one two three);
    

    Both of these are equivalent. You also may see it this way:

    my @array = qw/one two three/;
    

    I like the parentheses, but the forward slashes tend to be the standard.

    Method #3: Be Nice When Exporting

    It is not recommended you use automatic exporting any more. Older modules like File::Copy still do it, but newer modules make you import your stuff. This also uses the Exporter pragma, but I specify @EXPORT_OK instead of just @EXPORT.

    Now, when I specify I want to use Local::Base, I have to specify the functions I want to import into my program:

    My Program

    use strict;
    use warnings;
    use feature qw(say);
    
    use Local::Base qw(foo);
    
    my $foo_string = foo("string");
    say "Foo: $foo_string";
    

    Local/Base.pm

    package Local::Base;
    use strict;
    use warnings;
    
    use Exporter 'import';
    
    our @EXPORT_OK; = qw(foo);
    
    sub foo {
        my $string = shift;
    
        return qq(I've foo'd "$string"!);
    }
    
    1;
    

    This forces the user to document the functions in your module they want to use. This way, they know where imported functions came from. It enforces good programming practice. Plus, if you use multiple modules and they have similar function names, you can make sure you use the one from the module you want. (Remember, you can still specify the package name prefixed before the function if you want to use the other one).

    What if I am a Python programmer and I don't care about good programming practices? (Wait, that didn't come out quite right...) You can still (sort of) do it the Python way by specifying a Regular Expression (after all this is Perl):

    use Local::Base '/.+/';
    

    This will export all modules listed in both @EXPORT and @EXPORT_OK that match this regular expression. Since this matches everything, it will import everything you listed in @EXPORT and @EXPORT_OK. It won't import all functions. It will only import the functions in the @EXPORT and @EXPORT_OK arrays. Of course, you can specify any regular expressions and even ant-regular expressions. This will export all exportable functions except those with bar in the name:

    use Local::Base '!/bar/';
    

    Take a look at the Exporter pragma, and see what other goodies it has. For example, you can group functions into tags. That way, users can specify a particular set of functions with just a tag. See Math::Trig for a good example.

    Hope this helps.

    Sorry for the long answer, but I'm married with kids. Like, I'm doing anything else on New Years Eve.