Pregunta

En Perl, es posible crear una variable global basado en una cadena?

por ejemplo, si tuviera una función como:.

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

y lo llamé gusto:

create_glob_var( "bar" );

¿Cómo podría modificar create_glob_var para realmente crear una variable global llamada $bar?

Mi proyecto está usando Perl 5.8.5.

Editar

La siguiente no funciona:

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: Soy consciente de que el uso de variables globales provoca agotamiento del ozono y masculina La calvicie de patrón . Estoy tratando de limpiar un poco el código heredado que ya está completamente infectada con el uso de variables globales. Una refactor a la vez ...

¿Fue útil?

Solución

Si usted está tratando de limpiar el código de edad, puede escribir un módulo que exporta la variable (s) requerida. Cada vez que sienta la necesidad de invocar create_glob_var, en vez agregar una variable a este paquete y ponerlo en la lista de importación.

Esto ayudará a mantener un registro de lo que está pasando y cómo se utilizan las variables.

package MyVars;

use strict; use warnings;

use Exporter 'import';

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

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

La secuencia de comandos:

#!/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);

Salida:

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

Otros consejos

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

El no strict 'refs' sólo es necesario si use strict es, en efecto, que debe ser siempre.

Adición:

Si estás preguntando si hay una manera de escribir una subrutina create_glob_var de tal manera que el siguiente código tendrá éxito:

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

... entonces la respuesta es "No" Sin embargo, Pragma vars de Perl hará lo que quiere:

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

Pero esto es una especie de viejo estilo Perl codificación. Hoy en día, uno puede normalmente hacer esto:

use strict;
our $bar = "blah";

our puede también acaba de declarar las variables globales que pueden ser utilizados libremente después:

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

Trate de mirar a esta pregunta: ¿Se Perl tienen variables dinámicas PHP-como?

En resumen, parece que usted debería ser capaz de hacer $$glob_var_str = "whatever";

Usted tendría que utilizar un eval, pero eso es generalmente considerado como el mal. Algo así como:

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

editar

Sólo comprobado que sólo se puede hacer esto sin la my y con no strict refs.

El vars pragma ya lo hace el trabajo pesado por lo que quiere, por lo que lo puso a trabajo:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

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

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

Si prefiere deletrearlo create_glob_var, a continuación, utilizar

#! /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";

De cualquier manera, la salida es

blah

Tengo curiosidad por saber por qué desea hacerlo de esta manera en lugar de declarar estas variables con our . Sí, puede tomar unas pocas iteraciones para atraparlos a todos, pero éstas son soluciones a corto plazo de todos modos, ¿verdad?

En general, se puede utilizar una variable como nombre de variable (ver "referencias simbólicas "en perlref ), pero que realmente, realmente, realmente no quiere hacer eso:. permitiendo al pragma strict 'refs' desactiva esta función

Rafael García-Suárez mostró gran sabiduría cuando escribió: “No sé cuál es su problema original es, pero mejor utilizar un hash.”

Vea también:

Respuesta de Sinan Unur es sin duda la mejor. Sin embargo, este cogió mi curiosidad, así que lo hice un poco de lectura (perlmod perldoc) y aprendió acerca de "package_name ::" de hash como una manera de acceder al espacio de nombres de un paquete.

El siguiente código añade un registro a la tabla de símbolos del principal :: paquete:

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

print "$main::blah\n";

Esta impresiones "sss".

Sin embargo, he tenido que añadir el nombre del paquete de impresión a la declaración porque "use strict" aún no se deje engañar. Voy a seguir buscando -. No parece use vars a trabajar en el momento

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top