如何在Perl中使用符号引用?

如何在Perl中使用符号引用?,perl,variables,Perl,Variables,在Perl中,如果一个变量包含另一个变量的名称,如何使用第一个变量访问另一个变量 例如,让 $name = "bob"; @bob = ("jerk", "perlfan"); 我应该如何使用$name来了解bob是什么样的人? 虽然我不太确定,但我模糊的记忆告诉我这可能与typeglob有关。这是一种非常糟糕的做法。如果你曾经需要这样做,这意味着你应该重构你的代码。也许使用命名键的哈希会更好: my %data = ( 'bob' => [ 'jerk', 'perlfan'

在Perl中,如果一个变量包含另一个变量的名称,如何使用第一个变量访问另一个变量

例如,让

$name = "bob";
@bob = ("jerk", "perlfan");
我应该如何使用$name来了解bob是什么样的人?
虽然我不太确定,但我模糊的记忆告诉我这可能与typeglob有关。

这是一种非常糟糕的做法。如果你曾经需要这样做,这意味着你应该重构你的代码。也许使用命名键的哈希会更好:

my %data = (
    'bob' => [ 'jerk', 'perlfan' ],
);
my $name = 'bob';

print $data{ $name }->[0], "\n";
print $data{ $name }->[1], "\n";

my $stringified = join ' and ', @{ $data{ $name } };
print $stringified, "\n";

你真的不应该这么做,看看depesz的答案,但是

{
    no strict 'refs';
    print join(q{, }, @$name);
}
是的,您可以使用字符串标量作为变量引用,它会按名称查找变量

您也可以使用typeglobs执行此操作,有关简单方法,请参见符号模块。

几点:

  • 您不是在谈论typeglobs,而是在谈论符号引用
  • 不要使用符号引用——它们会导致难以追踪的bug
  • 几乎在任何情况下,符号引用似乎都是一个好主意,使用基于散列的数据结构是最好的方法
  • 考虑使用Hash::Util在您不想更改哈希时锁定它们
  • 符号引用对词汇变量不起作用
  • Typeglobs对词汇变量不起作用
  • 使用词汇变量
  • 不要使用符号引用
有关引用(符号或其他)的详细信息,请参见。 有关使用数据结构的帮助,请参阅。 有关typeglobs的更多信息,请参阅。 有关词法变量的更多信息,请参阅

下面是一个使用锁定哈希来根据变量内容控制数据访问的示例:

use strict;
use warnings;
use Hash::Util qw( lock_hash unlock_hash );

my %data;
lock_hash( %data );
#Altering %data is a fatal exception.

unlock_hash( %data );

%data = (
    'bob' => [ 'jerk', 'genius' ],
);
lock_hash( %data );


for my $name (qw/ bob  margaret /) {
    my $info = $data{$name}; # Fatal error when accessing data for margaret.
    print "$name is a\n";
    print map "\t$_\n", @$info;
}
抛开所有警告不谈,如果需要使用符号引用(但不需要),则使用符号引用的语法是:

注意,数组
@bob
是用
our
声明的。符号引用仅适用于符号表中的值。换句话说,词汇变量不适用于符号引用

为了防止我没有充分强调这一点,不要使用符号引用

请参见:

初学者通常认为他们想要一个包含变量名的变量


简短的回答:不要。详细解答:阅读常见问题解答条目(也可在您的计算机上找到)。较长的答案:阅读MJD的(,)。

通常当您认为需要使用符号引用时,使用哈希(关联数组)会更好

结果:

jerk perlfan mary had a little lamb susan not found 返回:

jerk perlfan # mary is not an array, it's a scalar mary had a little lamb susan not found 杰克帕尔凡 #mary不是数组,而是标量 玛丽有一只小羊羔 苏珊没有找到
您应该注意到,很难安全地使用符号引用,这就是为什么不应该使用它们的原因


当然,除非你是做一些高级工作的专家。

符号引用是值得避免的,但是如果你真的想使用它们,它们的使用语法与常规引用相同:请参阅。

+1以获得技术上正确的答案,并同意你永远不应该这样做。完全正确。在第二颗子弹之后,你很容易就停下来了。我相应地编辑了问题的标题。+1从技术上正确、令人惊讶地全面地解释了如何做以及为什么不做。+1避免不良做法要比找到使不良做法发生的方法好得多。这就是象征性引用所做的:邪恶在于,通过使用象征性引用,一种是将程序的符号表视为自己的私有哈希,当然,它不是。所以,使用散列。不要使用符号引用。(我认为这一点强调得不够)。
use strict;
use warnings;

my %user = (
  'bob' => [qw' jerk perlfan '],
  'mary' => 'had a little lamb',
);

{
  for my $name (qw'bob mary susan'){
    if( exists $user{$name} ){

      if( ref($user{$name}) eq 'ARRAY' ){
        print join( ' ', @{$user{$name}} ), "\n";

      }else{
        print $name, ' ', $user{$name}, "\n";
      }

    }else{
      print "$name not found\n";
    }
  }
}
jerk perlfan mary had a little lamb susan not found
use strict;
use warnings;

# can't use my
our @bob = ("jerk", "perlfan");
our $mary = 'had a little lamb';

{
  for my $name (qw'bob mary susan'){
    if( exists $::{$name} ){
      my $ref = $::{$name};

      if( *{$ref}{ARRAY} ){
        print join(' ',@$ref), "\n";

      }elsif( *{$ref}{SCALAR} ){
        print "# $name is not an array, it's a scalar\n";
        print $name, ' ', $$ref, "\n";
      }

    }else{
      print "$name not found\n"
    }
  }
}
jerk perlfan # mary is not an array, it's a scalar mary had a little lamb susan not found