Question

En Perl, est-il possible de créer une variable globale basée sur une chaîne?

par exemple, si j'avais une fonction comme:.

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

et je l'ai appelé comme:

create_glob_var( "bar" );

Comment pourrais-je modifier create_glob_var réellement créer une variable globale appelée $bar?

Mon projet utilise Perl 5.8.5.

EDIT

Ce qui suit ne fonctionne pas:

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";

Produit:

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.

NOTE Je me rends compte que l'utilisation des variables globales provoque appauvrissement de l'ozone et des hommes calvitie . Je suis en train de nettoyer un code existant qui est déjà complètement infecté par l'utilisation des variables globales. Un refactor à la fois ...

Était-ce utile?

La solution

Si vous essayez de nettoyer l'ancien code, vous pouvez écrire un module qui exporte la variable requise (s). Chaque fois que vous ressentez le besoin d'invoquer create_glob_var, ajouter à la place une variable à ce paquet et le mettre dans la liste des importations.

Cela vous aidera à garder une trace de ce qui se passe et comment les variables sont utilisées.

package MyVars;

use strict; use warnings;

use Exporter 'import';

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

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

Le script:

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

Sortie:

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

Autres conseils

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

Le no strict 'refs' est nécessaire que si use strict est en vigueur, ce qui devrait toujours être.

Addendum:

Si vous vous demandez s'il y a un moyen d'écrire un sous-programme create_glob_var de telle sorte que le code suivant réussira:

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

... alors la réponse est « Non » Cependant, la pragma vars Perl fera ce que vous voulez:

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

Mais ce genre est de style ancien de codage Perl. De nos jours, on en général faire ceci:

use strict;
our $bar = "blah";

our peut également déclarer que les variables globales qui peuvent être librement utilisées par la suite:

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

Essayez de regarder cette question: que Perl a des variables dynamiques PHP comme

En bref, il semble que vous devriez être en mesure de le faire $$glob_var_str = "whatever";

Vous devez utiliser un eval, mais qui est généralement considéré comme le mal. Quelque chose comme:

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

EDIT

Juste vérifié que vous ne pouvez le faire sans my et no strict refs.

Le vars pragma fait déjà le levage de charges lourdes pour ce que vous voulez, donc mis à travail:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

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

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

Si vous préférez épelle create_glob_var, puis utilisez

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

Quoi qu'il en soit, la sortie est

blah

Je suis curieux de savoir pourquoi vous voulez le faire de cette façon plutôt que de déclarer ces variables avec our . Oui, il peut prendre quelques itérations pour les attraper tous, mais ceux-ci sont de toute façon des solutions à court terme, non?

En général, vous pouvez utiliser une variable comme nom de variable (voir "Les références symboliques "dans perlref ), mais vous avez vraiment, vraiment, vraiment ne voulez pas faire. permettant la pragma strict 'refs' désactive cette fonctionnalité

Rafael Garcia-Suarez a montré une grande sagesse quand il écrit: « Je ne sais pas ce que votre problème d'origine, mais je suggère d'utiliser un hachage. »

Voir aussi:

Réponse par Sinan Unur est en effet le meilleur. Cependant, cette curiosité a pris ma, alors je l'ai un peu de lecture (perldoc perlmod) et appris « package_name :: » hash comme un moyen d'accéder à l'espace de noms d'un package.

Le code suivant ajoute un enregistrement à la table des symboles de main :: package:

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

print "$main::blah\n";

Cette affiche "sss".

Cependant, je devais ajouter le nom du package à la déclaration d'impression parce que « use strict » est toujours pas dupe. Je vais continuer à chercher -. Vars d'utilisation ne semble pas fonctionner au moment

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top