2012-07-29 17 views
7

pragmi, come autodie, secondo i documenti, sono lessicamente scoped.pragmi con ambito lessicale

{ 
use autodie; 
.. 
.. 
} 
# Can die here 

si applica a tutti i moduli caricati con use? per quanto ne so, l'uso è quasi lo stesso di:

BEGIN { 
require autodie; 
autodie->import(LIST); 
} 

BEGIN accade al momento della compilazione, richiedono non è con scope lessicale, così come mai che autodie a conoscenza circa la sua portata?

Grazie,

+0

C'è qualcosa che volevi fare? O è solo per curiosità? – ikegami

risposta

10

La risposta breve è che lessicalmente con ambito pragmatic modules sono esplicitamente scritti a comportarsi in quel modo, e utilizzare le variabili interne magici $^H e %^H durante la fase di compilazione per attivare e disattivare funzionalità.

Il compilatore fa la sua parte localizzando implicitamente queste variabili in modo che il loro valore venga ripristinato al termine della compilazione di un blocco di codice a quello che era all'inizio. In questo modo fornisce le basi della semantica lessicale.

Originariamente era disponibile solo la variabile $^H. Contiene una maschera di bit che stabilisce quali opzioni del compilatore sono disponibili in qualsiasi momento durante la compilazione. Per questo motivo, gli unici pragmi lessicali che potevano essere scritti erano quelli che manipolavano il set definito di bit magici in $^H.

Successivamente è stato introdotto l'hash %^H e qualsiasi pragma può ora memorizzare valori in questo hash con chiavi che iniziano con il nome del pragma. Poiché il compilatore localizza l'hash allo stesso modo dello scalare, qualsiasi pragma può memorizzare qui informazioni sullo stato dell'ambito automaticamente.

Il modulo autodie non manipola nessuna di queste variabili, ma sottoclasse il modulo Fatal che fa tutto il duro lavoro. Usa %^H per tenere traccia di quali operatori sono stati resi fatali e si affida al compilatore per scartare queste informazioni alla fine del blocco.

+1

la menzione di perlpragma sarebbe buona – ysth

7

Dal metodo di importazione di Fatal.pm che è il backend di autodie, godere di questo:

# Dark magic to have autodie work under 5.8 
# Copied from namespace::clean, that copied it from 
# autobox, that found it on an ancient scroll written 
# in blood. 

# This magic bit causes %^H to be lexically scoped. 
$^H |= 0x020000; 

Quindi la risposta è lì davvero è un modo per rendere le importazioni consapevoli della loro lessicale portata, ma è profondamente intrecciato con il coraggio di Perl e non destinato ai programmatori ordinari da utilizzare.

+1

No, spiega solo il passaggio aggiuntivo necessario per fare in modo che la direttiva '%^H' funzioni in 5.8, non solo 5.10+. – ysth

+0

sì, ho davvero mostrato solo il pezzo più spaventoso per trasmettere un senso generale della magia coinvolta. Era una risposta nel senso che confermava la sensazione dell'osservatore che le direttive lessicali non possono essere implementate con tecniche di importazione dei moduli "normali". –

+1

ma è completamente sbagliato ... possono essere facilmente implementati. vedi http://perldoc.perl.org/perlpragma.html – ysth

1

Non è require che è interessante; è ciò che fa il pragma in import.

La maggior parte (tutti?) Della direttiva utilizza $^H o %^H. Il parser li localizza nello scope che viene analizzato, il che significa che li ripristina al valore che avevano prima di

Prendere il numero strict, ad esempio. Il suo import modifica $^H. $^H contiene una serie di flag che istruisce il compilatore su come comportarsi.

$ perl -e' 
    BEGIN { printf "%04X\n", $^H } 
    { 
     use strict; 
     BEGIN { printf "%04X\n", $^H } 
    } 
    BEGIN { printf "%04X\n", $^H } 
' 
0100 
0702 
0100 

$^H è riservato per l'utilizzo di Perl, ma allo stesso modo localizzato %^H è disponibile per uso generale. Ad esempio, feature::qw_comment si aggancia al parser una volta, quando viene caricato da require, ma non fa nulla a meno che lo $^H{'feature::qw_comments::'} non sia vero. L'importazione è equivalente a

sub import { $^H{'feature::qw_comments::'} = 1; }