How can I export all subs in a Perl package?
Asked Answered
A

9

22

I would like to expose all subs into my namespace without having to list them one at a time:

@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

Alphonsealphonsine answered 8/4, 2009 at 22:25 Comment(1)
Maybe if you could let us know why you want to do this. Just for kicks?Huffy
M
24

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Madagascar answered 8/4, 2009 at 23:58 Comment(11)
Doh! I tap-danced all around that solution without thinking about it. (But it does break the expectation that a module will have it's own namespace, which can surprise.)Huffy
How should I "load" the file?Alphonsealphonsine
OK, got it, changed use to do. ie. do "mymod.pm";Alphonsealphonsine
@VilleM require! do will reload the module each time it's called. require only loads once.Precentor
hmm, changing do to require doesn't work for some reason: ".pm did not return a true value at modtest.pl line 2"Alphonsealphonsine
That's an easy fix. Return a true value at the end of modtest.pl. That's why you see a lot of Perl modules ending in 1;Madagascar
@Schwern: but reloading every time is what is wanted, given that it may be loading into different packages different times.Petrology
ysth, exactly, using do works perfectly now, thanks, this the accepted answerAlphonsealphonsine
Old question, but curious - if you did want to keep the package, could you abuse @ISA? package main; use Foo; @ISA = qw(Foo);?Compendious
@vol7ron: @ISA lets you inherit methods, but you still can't call them as normal subroutines without the package specification.Madagascar
@briandfoy that makes sense and it would only work for methods in the parent, that are not defined in main (child). Also learned that use parent is now preferred over @ISA - go figure :)Compendious
L
11

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.

# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}
Luciana answered 9/4, 2009 at 0:15 Comment(1)
Also see Leon's answer in #607782Madagascar
P
3

Warning, the code following is as bad an idea as exporting everything:

package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux
Pulling answered 8/4, 2009 at 23:9 Comment(5)
Great, exactly what I was hoping, no standard way in exporter I guess, but this definitely does what I need, thanks muchAlphonsealphonsine
I think I'd just walk through the symbol table and look for defined code entries. There are too many ways that regex can fail.Madagascar
Could you elaborate on how to "walk through the symbol table"?Alphonsealphonsine
Yep, that is why I put the caveat on there that it was a bad idea. It was just the easiest way I could think of and if it causes problems, well, it shouldn't have been done in the first place.Pulling
Don't try to parse Perl code, /usr/bin/perl has already done that for you.Falzetta
P
2

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

Petrology answered 8/4, 2009 at 22:26 Comment(2)
was this what you were thinking of? search.cpan.org/dist/Exporter-NoWork/lib/Exporter/NoWork.pmPulling
@Chas. Owens - no, I was thinking of Exporter::SimplePetrology
H
2

You can always call subroutines in there fully-specified form:

MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

Huffy answered 8/4, 2009 at 22:33 Comment(3)
Yes, I am aware of that, but how about not having to say MyModule:: for every sub? I am looking for EXPORT ALL?Alphonsealphonsine
@Ville M: It's often hard to know what someone else is aware of if they don't say it. ;-)Huffy
Something about sound and tree falling in the forest comes to mind... anyway, thanks for your helpAlphonsealphonsine
A
2

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Analysand answered 11/10, 2014 at 18:23 Comment(0)
B
1

Although it is not usually wise to dump all subs from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Brow answered 2/4, 2013 at 0:32 Comment(0)
D
1

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

#!/usr/bin/perl
use strict;
use warnings;
use mycommon;

common::onefunctionthatyoumadeonlibary()

case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

Dissepiment answered 14/11, 2013 at 21:38 Comment(0)
S
-1

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Shulem answered 8/4, 2009 at 22:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.