ProgrammazioneSviluppatore Backend

Come funzionano le variabili lessicali e di pacchetto in Perl: quali sono le differenze tra my, our e state, quando usarle correttamente e quali errori si incontrano nella pratica?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Perl ci sono tre tipi principali di dichiarazione delle variabili: my, our e state.

  • my crea una variabile lessicale con ambito di visibilità all'interno del blocco di codice (scoping lessicale).
  • our crea una variabile di pacchetto, accessibile globalmente all'interno del pacchetto, ma visibile solo nel blocco lessicale. È utile per organizzare spazi dei nomi tra i moduli.
  • state è stato aggiunto in Perl 5.10 e crea una variabile lessicale che conserva il valore tra le chiamate della sottoprogrammazione (di fatto, una variabile statica).
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Restituisce 1, poi 2, poi 3 }

Dove usarle correttamente:

  • my — è quasi sempre la scelta preferita per le variabili, se non ci sono motivi per un accesso globale.
  • our — per esportare variabili tra i moduli, quando è necessario un uso condiviso.
  • state — nel caso in cui la variabile debba "ricordare" un valore tra le chiamate di funzione (ad esempio, un contatore di chiamate).

Domanda ingannevole

Può una variabile dichiarata con our essere catturata (captured) in una chiusura come my?

Di solito si risponde "sì, è conveniente", ma non è così. La variabile our è globale per il pacchetto, e la chiusura non sta legando il suo valore al momento della creazione della chiusura, ma accedendo attraverso il nome globale. Pertanto, il suo "valore" può cambiare esternamente alla chiusura e influenzare tutte le chiusure!

our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Restituisce 42, non 10

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze dell'argomento


Storia

In un grande script per il parsing dei log, le variabili venivano dichiarate tramite our per "accesso conveniente" da diverse funzioni del modulo. Di conseguenza, la modifica di queste variabili in una funzione portava a comportamenti inaspettati in un'altra, rompendo l'elaborazione parallela dei log.


Storia

L'uso di my per variabili di cui era necessario mantenere il valore tra le chiamate di funzione (ad esempio, un contatore all'interno di una traversata ricorsiva) portava al reset del valore ad ogni chiamata, causando una logica di traversata errata. Sostituirlo con state ha risolto la situazione.


Storia

L'uso scorretto di our in un modulo importato (esportazione di variabili non tramite Exporter) ha causato collisione di nomi durante il caricamento di due moduli diversi che usavano lo stesso nome di variabile. Di conseguenza, i dati "saltavano" da un contesto all'altro.