Domanda

In Perl è possibile creare una variabile globale basata su una stringa?

Ad esempio, se avessi una funzione come:

sub create_glob_var {
    my ($glob_var_str) = @_;
    # something like this ( but not a hash access).
    our ${$glob_var_str};
};

e l'ho chiamato così:

create_glob_var( "bar" );

Come potrei modificare create_glob_var per creare effettivamente una variabile globale chiamata $bar?

Il mio progetto utilizza Perl 5.8.5.

MODIFICARE

Quanto segue non funziona:

use strict;
BEGIN {
  sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
  }

  create_glob_var("bah");
};

$bah = "blah";

Produce:

Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.

NOTA Mi rendo conto che l'uso delle variabili globali causa riduzione dell’ozono e calvizie maschile.Sto cercando di ripulire del codice legacy che è già completamente infetto dall'uso delle variabili globali.Un refactoring alla volta...

È stato utile?

Soluzione

Se stai cercando di ripulire il vecchio codice, puoi scrivere un modulo che esporti le variabili richieste.Ogni volta che senti il ​​bisogno di invocare create_glob_var, aggiungi invece una variabile a questo pacchetto e inseriscila nell'elenco di importazione.

Ciò ti aiuterà a tenere traccia di cosa sta succedendo e di come vengono utilizzate le variabili.

package MyVars;

use strict; use warnings;

use Exporter 'import';

our($x, %y, @z);

our @EXPORT_OK = qw( $x %y @z );

Il copione:

#!/usr/bin/perl

use strict;use warnings;

use MyVars qw( $x %y @z );

$x = 'test';
%y = (a => 1, b => 2);
@z = qw( a b c);

use Data::Dumper;
print Dumper \($x, %y, @z);

Produzione:

$VAR1 = \'test';
$VAR2 = {
          'a' => 1,
          'b' => 2
        };
$VAR3 = [
          'a',
          'b',
          'c'
        ];

Altri suggerimenti

sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
}

IL no strict 'refs' è necessario solo se use strict è in vigore, come dovrebbe sempre essere.

Addendum:

Se stai chiedendo se esiste un modo per scrivere una subroutine create_glob_var in modo tale che il seguente codice abbia esito positivo:

use strict;
create_glob_var("bar");
$bar = "whatever";

... allora la risposta è "No." Tuttavia, Perl's vars pragma farà quello che vuoi:

use strict;
use vars qw($bar);
$bar = "whatever";

Ma questa è una specie di codifica Perl vecchio stile.Al giorno d'oggi, in genere si farebbe questo:

use strict;
our $bar = "blah";

our può anche semplicemente dichiarare variabili globali che possono essere utilizzate liberamente in seguito:

our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');

Prova a guardare questa domanda:Perl ha variabili dinamiche simili a PHP?

In breve, sembra che dovresti essere in grado di farlo $$glob_var_str = "whatever";

Dovresti usare un eval, ma questo è generalmente considerato malvagio.Qualcosa di simile a:

eval("$glob_var_str = \@_;");

MODIFICARE

Ho appena verificato che puoi farlo solo senza il my e con no strict refs.

IL vars pragma fa già il lavoro pesante per quello che vuoi, quindi mettilo al lavoro:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

BEGIN { vars->import(qw/ $bah /) }

$bah = "blah";
print $bah, "\n";

Se preferisci scriverlo create_glob_var, quindi utilizzare

#! /usr/bin/perl

use warnings;
use strict;
use vars;

sub create_glob_var { vars->import("\$$_[0]") }

BEGIN { create_glob_var "bah" }

$bah = "blah";
print $bah, "\n";

In ogni caso, l'output lo è

blah

Sono curioso di sapere perché vuoi farlo in questo modo invece di dichiarare queste variabili our.Sì, potrebbero essere necessarie alcune iterazioni per catturarli tutti, ma si tratta comunque di soluzioni a breve termine, giusto?

In generale, è possibile utilizzare una variabile come nome di variabile (vedi "Riferimenti simbolici" in perlref), ma tu davvero, davvero, Veramente non voglio farlo:abilitando il strict 'refs' pragma disabilita questa funzionalità.

Rafael Garcia-Suarez ha mostrato grande saggezza quando ha scritto: "Non so quale sia il tuo problema originale, ma suggerisco di usare un hash".

Guarda anche:

La risposta di Sinan Ünür è davvero la migliore.Tuttavia, questo ha stuzzicato la mia curiosità, quindi ho letto un po' (perldoc perlmod) e ho scoperto che l'hash "package_name::" è un modo per accedere allo spazio dei nomi di un pacchetto.

Il codice seguente aggiunge un record alla tabella dei simboli di main::pacchetto:

use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;

print "$main::blah\n";

Questo stampa "sss".

Tuttavia, ho dovuto aggiungere il nome del pacchetto all'istruzione print perché "use strict" non è ancora ingannato.Continuerò a cercare: l'uso di vars non sembra funzionare al momento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top