2009-04-08 10 views
18

Ich möchte alle Subs in meinem Namespace verfügbar machen, ohne sie einzeln aufzulisten:Wie kann ich alle Subs in einem Perl-Paket exportieren?

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

Die Verwendung vollständig qualifizierter Namen würde einige Änderungen am vorhandenen Code erfordern, also würde ich das lieber nicht tun.

Gibt es @EXPORT_ALL?

Ich denke, die Dokumentation sagt, es ist eine schlechte Idee, aber ich würde es trotzdem tun oder zumindest wissen wie.

Um Jons Warum zu beantworten: Im Moment möchte ich für ein schnelles Refactoring eine Menge Subs in ihr eigenes Paket mit wenig Aufwand und Code-Änderungen zu den existierenden Skripten (wo diese Subs aktuell verwendet und oft wiederholt werden) verschieben.

Außerdem war ich meistens nur neugierig. (da es so aussieht, als ob der Exporteur das als Standard-Feature hätte, aber etwas überraschend basierend auf Antworten, so weit es nicht ist)

+0

Vielleicht könnten Sie uns wissen lassen * warum * Sie dies tun wollen.Nur zum Spaß? –

+0

OK, einige warum hinzugefügt. –

Antwort

23

Führen Sie keinen Export durch, und deklarieren Sie keinen Paketnamen in Ihrer Bibliothek. Laden Sie einfach die Datei mit require und alles wird im aktuellen Paket sein. Kinderleicht.

+0

Ausgezeichnete Antwort! –

+0

Doh! Ich habe überall um diese Lösung herum getanzt, ohne darüber nachzudenken. (Aber es bricht die Erwartung, dass ein Modul seinen eigenen Namensraum haben wird, der überraschen kann.) –

+3

Wie soll ich die Datei "laden"? –

2

Sie können immer voll spezifizierten Form dort Subroutinen nennen:

MyModule::firstsub(); 

Für Module, die ich intern schreibe, finde ich, dass diese Konvention ziemlich gut funktioniert. Es ist ein wenig mehr Tipparbeit, aber tendenziell bessere Dokumentation.

Werfen Sie einen Blick auf perldoc perlmod für weitere Informationen über das, was Sie erreichen möchten.

Allgemeiner könnten Sie den Code Exporter betrachten und sehen, wie er glob aliasing verwendet. Oder Sie können den Namensraum Ihres Moduls untersuchen und jede Subroutine exportieren. (Ich kümmere mich nicht zu suchen, wie das im Moment zu tun, aber Perl macht dies ziemlich einfach.) Oder Sie könnten nur Ihre Subroutinen in dem main Paket kleben:

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

(Ich glaube nicht, das ist eine gute Idee, aber Sie wissen besser als ich, was Sie versuchen zu erreichen.)

Es ist nichts falsch daran, dies zu tun vorausgesetzt, Sie wissen, was Sie tun und nicht nur versuchen zu vermeiden, an Ihre denken Schnittstelle zur Außenwelt.

+0

Ja, das ist mir bewusst, aber wie wäre es mit MyModule :: für jedes Sub? Ich suche nach EXPORT ALL? –

+0

@Ville M: ​​Es ist oft schwer zu wissen, was jemand anderes weiß, wenn er es nicht sagt. ;-) –

+0

Irgendetwas über den Klang und den Baum, der in den Wald fällt, kommt mir in den Sinn ... jedenfalls, danke für deine Hilfe –

3

Warnung nach dem Code so schlimm ist eine Idee, wie der Export alles:

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__ 

Hier ist die einige Code, der das Modul verwendet:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Expo; 

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

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

Und hier ist seine Ausgabe:

+0

Großartig, genau das, was ich mir erhofft habe, kein Standardweg im Exporteur, aber das macht definitiv das, was ich brauche, Vielen Dank –

+1

Ich denke, ich würde einfach durch die Symboltabelle gehen und nach definierten Codeeinträgen suchen. Es gibt zu viele Möglichkeiten, dass Regex fehlschlagen kann. –

+0

Können Sie näher erläutern, wie Sie durch die Symboltabelle gehen? –

10

Nicht. Aber wenn Sie wirklich wollen ... schreiben Sie eine benutzerdefinierte import, die die Symboltabelle durchläuft und alle benannten Subroutinen exportiert.

# 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 }; 
    } 
} 
+0

Siehe auch Leon Antwort in http://stackoverflow.com/questions/607282/whats-the-best-way-to-discover- all-subroutines-a-perl-modul-hat –

2

Vielleicht würden Sie sich in einem der Export * Module auf CPAN interessiert sein, die man einfach durch Hinzufügen eines Attributs zu der Unter Definition markieren subs als exportierbar lässt? (Erinnern nicht, welches es war, though.)

+0

war das woran du gedacht hast? http://search.cpan.org/dist/Exporter-NoWork/lib/Exporter/NoWork.pm –

+0

@Chas. Owens - nein, ich habe an Exporter :: Simple gedacht – ysth

1

Obwohl es normalerweise nicht ratsam, all sub s aus dem Modul in den Anrufer-Namensraum zu entleeren, ist es manchmal sinnvoll ist (und mehr trocken!), Um automatisch @EXPORT_OK zu erzeugen und %EXPORT_TAGS Variablen.

Die einfachste Methode ist, den Exporter zu erweitern. Ein einfaches Beispiel ist so etwas wie diese:

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; 

Beachten Sie die Verwendung von goto, die uns von dem Anrufer Stapel entfernt.

Ein vollständigeres Beispiel finden Sie hier: http://pastebin.com/Z1QWzcpZ Es generiert automatisch Tag-Gruppen aus Subroutinen-Präfixen.

1

Fall 1

Bibliothek ist:

package mycommon; 

use strict; 
use warnings; 

sub onefunctionthatyoumadeonlibary() { 
} 
1; 

Sie es verwenden können, gemeinsame Aufruf :::

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

common::onefunctionthatyoumadeonlibary() 

Fall 2

Bibliothek ist, yousimple sie exportieren:

package mycommon; 

use strict; 
use warnings; 

use base 'Exporter'; 

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

Verwendung es in derselben „Namensraum“:

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

onefunctionthatyoumadeonlibary() 

Auch können wir eine Mischung aus diesen beiden Fällen tun, können wir mehr gemeinsame Funktionen exportieren, es zu benutzen, ohne die Pakete Namen und andere Funktionen aufrufen, die wir nur rufe es mit Paketnamen auf und diese müssen nicht exportiert werden.

Verwandte Themen