-+  Associazione
-+  Documenti
 |-  Modern Perl
 |-  Bibliografia
 |-  Articoli
 |-  Talk
 |-  Perlfunc
 |-  F.A.Q.
 |-  F.A.Q. iclp
-+  Eventi
-+  Community
-+  Blog
-+  Link
Corso di Perl



 


indietro

[28] Come posso usare una variabile come nome di una variabile?

I principianti spesso ritengono di voler avere una variabile che a sua volta contiene il nome di una variabile.

    $fred = 23;
    $nome_variabile = "fred";
    ++$$nome_variabile;  # $fred adesso vale 24

A volte funziona, ma è un'idea molto sbagliata, per due ragioni.

La prima ragione è che funziona solo con variabili globali. Questo vuol dire che se nell'esempio precedente $fred fosse una variabile lessicale creata con my(), il codice non funzionerebbe per niente: accedereste accidentalmente alla globale, saltando a piè pari la variabile lessicale privata. Le variabili globali non vanno bene perché possono facilmente dar luogo a conflitti accidentali, e in generale rendono il codice confuso e non scalabile.

I riferimenti simbolici sono proibiti quando la direttiva use strict è attiva. Non sono veri riferimenti e di conseguenza non sono soggetti al conteggio dei riferimenti e alla garbage collection.

L'altra ragione per cui usare una variabile per mantenere il nome di un'altra variabile è una cattiva idea è che la questione spesso scaturisce da una mancanza di comprensione delle strutture dati Perl, in particolare degli hash. Se usate i riferimenti simbolici di fatto state usando l'hash che contiene la tabella dei simboli del package come %main::) anziché un hash definito dall'utente. La soluzione è usare un hash vostro oppure un riferimento vero e proprio.

    $VARIABILI_UTENTE{"fred"} = 23;
    $nome_variabile = "fred";
    $VARIABILI_UTENTE{ $nome_variabile }++;  # non $$nome_variabile++

Stiamo usando l'hash %VARIABILI_UTENTE anziché i riferimenti simbolici. A volte capita durante la lettura di stringhe inserite dall'utente che contengono riferimenti a variabili che si vogliono espandere con i valori delle variabili del programma. Anche questa è una cattiva idea, poiché confonde gli spazi dei nomi indirizzabili dal programma e dall'utente. Anzichè leggere una stringa ed espanderla con gli effettivi contenuti delle variabili proprie del programma:

    $str = 'qui ci sono $fred e $barney';
    $str =~ s/(\$\w+)/$1/eeg;   # c'e` bisogno di un doppio eval

sarebbe meglio mantenere un hash come %VARIABILI_UTENTE e far sì che i riferimenti puntino in effetti ai contenuti di questo hash:

    $str =~ s/\$(\w+)/$VARIABILI_UTENTE{$1}/g;   # nessun /e

È più veloce, più pulito e più sicuro dell'approccio precedente. Naturalmente, non c'è bisogno del simbolo del dollaro. Potete usare uno schema personale per rendere le cose meno confuse, come ad esempio dei simboli di percentuale usati a mo' di parentesi, ecc.

    $str = 'qui ci sono %fred% e %barney%';
    $str =~ s/%(\w+)%/$VARIABILI_UTENTE{$1}/g;   # nessun /e

Un'altra ragione per cui le persone a volte pensano di volere una variabile che contiene il nome di una variabile è che non sanno come costruire opportune strutture usando gli hash. Ad esempio, diciamo che in un programma si vogliono due hash: %fred e %barney e si vuole adoperare un altro scalare per fare riferimento ad esse per nome.

    $nome = "fred";
    $$nome{MOGLIE} = "wilma";    # imposta %fred
    $nome = "barney";
    $$nome{MOGLIE} = "betty";    # imposta %barney

C'è ancora un riferimento simbolico, ed è ancora afflitto dai problemi elencati sopra. Sarebbe di gran lungo meglio scrivere:

    $gente{"fred"}{MOGLIE}   = "wilma";
    $gente{"barney"}{MOGLIE} = "betty";

E usate solo un hash a più livelli.

Le uniche occasioni in cui dovete assolutamente usare i riferimenti simbolici sono quelle in cui ci si deve riferire alla tabella dei simboli. Potrebbe essere perché si ha a che fare con qualcosa per cui non è possibile avere un riferimento, ad esempio il nome di un formato. Questa pratica potrebbe essere importante anche per le chiamate ai metodi, visto che per essere risolte, passano attraverso la tabella dei simboli.

In questi casi, dovreste disattivare strict 'refs' temporaneamente in maniera tale da poter trafficare con la tabella dei simboli. Ad esempio:

    @colori = qw(rosso blu verde giallo arancione porpora viola);
    for my $nome (@colori) {
        no strict 'refs';  # chiudi un occhio per tutto il blocco
        *$nome = sub { "<FONT COLOR='$nome'>@_</FONT>" };
    }

Tutte queste funzioni (rosso(), blu(), verde(), ecc.) sembrano separate, ma il codice della chiusura è stato compilato, in realtà, una volta sola.

Quindi, a volte potreste voler usare dei riferimenti simbolici per manipolare direttamente la tabella dei simboli. Non importa se si tratta di format, handle o subroutine, poiché sono sempre globali -- non potete usare my() su di loro. Per gli scalari, gli array e gli hash, però -- e di solito per le subroutine --, probabilmente volete usare solo hard reference.

vedi in inglese

AUTORE E COPYRIGHT

Copyright (c) 1997, 1998, 1999, 2000, 2001 Tom Christiansen e Nathan Torkington. Tutti i diritti riservati.

Questa documentazione è libera; puoi ridistribuirla e/o modificarla secondo gli stessi termini applicati al Perl.

Indipendentemente dalle modalitè di distribuzione, tutti gli esempi di codice in questo file sono rilasciati al pubblico dominio. Potete, e siete incoraggiati a farlo, utilizzare il presente codice o qualunque forma derivata da esso nei vostri programmi per divertimento o per profitto. Un semplice commento nel codice che dia riconoscimento alle FAQ sarebbe cortese ma non è obbligatorio.

D:
Progetti e documenti in rilievo
Corso di Perl Progetto pod2it
D:
La ML di Perl.it
mongers@perl.it è la lista ufficiale di Perl Mongers Italia per porre quesiti di tipo tecnico, per rimanere aggiornato su meeting, incontri, manifestazioni e novità su Perl.it.
Iscriviti!
D:
Annunci Google