Как я могу создать имя переменной Perl на основе строки?

В Perl действительно ли возможно создать глобальную переменную на основе строки?

Например, если у меня была функция как:

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

и я назвал его как:

create_glob_var( "bar" );

Как я мог изменить create_glob_var на самом деле создать названную глобальную переменную $bar?

Мой проект использует жемчуг 5.8.5.

Править

Следующее не работает:

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

Производит:

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.

ОБРАТИТЕ ВНИМАНИЕ, что я понимаю, что использование глобальных переменных вызывает истончение озонового слоя и мужское облысение. Я пытаюсь очистить некоторый унаследованный код, который уже полностью заражен использованием глобальных переменных. Каждый осуществляет рефакторинг за один раз...

7
задан Jon Seigel 15 February 2011 в 17:51
поделиться

6 ответов

Если вы пытаетесь очистить старый код, вы можете написать модуль, который экспортирует необходимые переменные. Каждый раз, когда вы чувствуете необходимость вызвать create_glob_var , вместо этого добавьте переменную в этот пакет и поместите ее в список импорта.

Это поможет вам отслеживать, что происходит и как используются переменные.

package MyVars;

use strict; use warnings;

use Exporter 'import';

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

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

Сценарий:

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

Вывод:

$VAR1 = \'test';
$VAR2 = {
          'a' => 1,
          'b' => 2
        };
$VAR3 = [
          'a',
          'b',
          'c'
        ];
5
ответ дан 6 December 2019 в 14:04
поделиться

Попробуйте ответить на этот вопрос: Есть ли в Perl динамические переменные, подобные PHP?

Вкратце, это похоже на вы должны уметь делать $$ glob_var_str = "something";

2
ответ дан 6 December 2019 в 14:04
поделиться

Вам придется использовать eval, но это обычно считается злом. Что-то вроде:

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

EDIT

Только что проверил, что это можно сделать только без my и с no strict refs.

2
ответ дан 6 December 2019 в 14:04
поделиться

Прагма vars уже делает тяжелую работу для того, что вы хотите, поэтому используйте ее:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

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

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

Если вы предпочитаете напишите create_glob_var , затем используйте

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

В любом случае, результат будет

blah

. Мне любопытно узнать, почему вы хотите сделать это таким образом, а не объявлять эти переменные с помощью нашего . Да, может потребоваться несколько итераций, чтобы уловить их все, но в любом случае это краткосрочные исправления, не так ли?

В общем, вы можете использовать переменную в качестве имени переменной (см. «Символические ссылки» в perlref ), но вы действительно, действительно не хотите этого делать: включение прагмы strict 'refs' отключает эту функцию.

Рафаэль Гарсиа-Суарес проявил большую мудрость, когда написал: «Я не знаю, в чем заключается ваша первоначальная проблема, но я предлагаю использовать хеш».

См. Также:

2
ответ дан 6 December 2019 в 14:04
поделиться
sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
}

no strict 'refs' необходимо только в том случае, если действует use strict , что всегда должно быть быть.

Приложение:

Если вы спрашиваете, есть ли способ написать подпрограмму create_glob_var , чтобы следующий код был успешным:

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

... тогда ответ - «Нет». Однако прагма Perl vars сделает то, что вы хотите:

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

Но это своего рода кодирование Perl в старом стиле. В настоящее время обычно можно поступить так:

use strict;
our $bar = "blah";

наш может также просто объявлять глобальные переменные, которые можно свободно использовать позже:

our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');
3
ответ дан 6 December 2019 в 14:04
поделиться

Ответ Sinan Ünür действительно лучший. Однако это пробудило мое любопытство, поэтому я немного почитал (perldoc perlmod) и узнал о хэше "имя_пакета::" как способе доступа к пространству имен пакета.

Следующий код добавляет запись в таблицу символов пакета main::

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

print "$main::blah\n";

Это выводит "sss".

Однако мне пришлось добавить имя пакета в оператор печати, потому что "use strict" все еще не обманывает. Я продолжу поиски - use vars, похоже, не работает в данный момент.

1
ответ дан 6 December 2019 в 14:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: