2016-07-05 26 views
9

Ho un modulo chiamato hsfSubs.pm nella mia cartella perl\lib. Non ho nulla nel modulo ma subroutine e 1; alla fine.In Perl, perché ho bisogno di esportatore?

Una subroutine, ad esempio, è denominata pause. Non ho implementato alcuna routine di importazione o esportazione.

Nei miei programmi principali, dico semplicemente use hsfSubs; e successivamente posso chiamare senza problemi pause. Idem se dico use hsfSubs qw(pause);.

Perché dovrei usare Esportatore, @EXPORT e @EXPORT_OK, ecc. O altre complicazioni?

Le risposte multiple su Stack Overflow a domande su Esportatore indicano come utilizzarlo, ma non riesco a capire perché utilizzarlo.

risposta

13

La versione breve è che si desiderava un modulo, ma si è finito con quello che this chiama una libreria. Questi non sono buoni perché inquinano lo spazio dei nomi del chiamante (che può causare molti problemi). Ma ancora più importante, caricarli usando require o use (come opposto a do) è buggato.

Se fosse stato scritto correttamente come modulo, il tuo esempio non funzionerebbe. L'esportatore è la soluzione a questo problema.


Entriamo nei dettagli.

Come ho già detto, c'è un problema con il modulo. Come hai notato, a volte funziona nonostante l'errore.

$ cat Buggy.pm 
sub test { "ok!" } 
1; 

$ perl -e'use Buggy; CORE::say(test());' 
ok! 

Ma questo è solo perché il tuo esempio è troppo semplice. Aggiungiamo al modulo un modulo [1] correttamente scritto.

$ cat Buggy.pm 
sub test { "ok!" } 
1; 

$ cat Other.pm 
package Other; 
use Buggy; 
1; 

$ perl -e'use Other; use Buggy; CORE::say(test());' 
Undefined subroutine &main::test called at -e line 1. 

Il bug nel modulo è che non ha una direttiva package. I moduli caricati utilizzando use e require devono sempre utilizzare una direttiva package. Ma non appena lo aggiungi, il tuo modulo smette di funzionare.

$ cat NotBuggy.pm 
package NotBuggy; 
sub test { "ok!" } 
1; 

$ perl -e'use NotBuggy; CORE::say(test());' 
Undefined subroutine &main::test called at -e line 1. 

L'esportatore è utilizzato per risolvere questo problema.

$ cat Final.pm 
package Final; 
use Exporter qw(import); 
our @EXPORT = qw(test); 
sub test { "ok!" } 
1; 

$ perl -e'use Final; CORE::say(test());' 
ok! 

  1. Beh, non proprio. Se è stato scritto correttamente, dovrebbe includere use strict; use warnings 'all';. Includilo sempre! È stato omesso qui per mantenere le cose visivamente semplici.
+0

Grazie. Vedo la differenza Ma una "biblioteca" è davvero ciò che volevo. L'unica ragione per cui potrei volere un modulo è se non ci fosse un altro modo per ottenere una libreria. È bizzarro dire che se lo avessi scritto correttamente non avrebbe funzionato. LOL. Suppongo che l'inquinamento sia nella mente di chi guarda. Non considero l'accesso alle mie subroutine come inquinamento. La complessità inutile è l'inquinamento. – user1067305

+1

L'inquinamento non è la presenza di cose ricercate; è la presenza di cose indesiderate.Il problema è che hai accesso non solo ai sottotitoli che vuoi esportare, ma anche ai sottotitoli interni al tuo modulo. È l'equivalente sub delle variabili globali. La programmazione è tutta una questione di limiti, esattamente l'opposto di ciò che hai detto è buono. Rendere tutto globale rende le cose più difficili da leggere, eseguire il debug, mantenere, ecc. Ecc. No, questo non è un problema di stile. La totalità dei programmatori Perl ha smesso di usare queste "librerie" quando Perl ha aggiunto il supporto per lo spazio dei nomi 20 anni fa. – ikegami

+6

Per farla breve, compartimentare il codice richiede un piccolo codice in più, ma rende il programma molto * meno * complesso. – ikegami

Problemi correlati