简体   繁体   English

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

[英]How do I use symbolic references in Perl?

In Perl, if a variable holds the name for another variable, how do I use the first variable to visit the other one? 在Perl中,如果变量保存另一个变量的名称,如何使用第一个变量访问另一个变量?

For example, let 例如,让我们

$name = "bob";
@bob = ("jerk", "perlfan");

how should I use $name to get to know what kind of person bob is? 我该怎么用$ name来了解bob是什么样的人? Although I'm not quite sure, my vague memory tells me it might related to typeglob. 虽然我不太确定,但我模糊的记忆告诉我它可能与typeglob有关。

Several points: 几点:

  • You aren't talking about typeglobs, you are talking about symbolic references . 你不是在谈论typeglobs,而是在谈论符号引用
  • Don't use symbolic references -- they lead to hard to track down bugs. 不要使用符号引用 - 它们导致难以追踪错误。
  • In almost any case where symbolic references seem like a good idea, using a data structure based on a hash is the best approach. 几乎在任何情况下,符号引用似乎都是一个好主意,使用基于哈希的数据结构是最好的方法。
  • Consider using Hash::Util to lock your hashes when you don't want to alter them. 当您不想更改它们时,请考虑使用Hash :: Util锁定哈希值。
  • Symbolic references don't work on lexical variables. 符号引用不适用于词法变量。
  • Typeglobs don't work on lexical variables. Typeglobs不适用于词法变量。
  • Use lexical variables. 使用词汇变量。
  • Don't use symbolic references. 不要使用符号引用。

See perlreftut for more on references (symbolic and otherwise). 有关参考文献的更多信息,请参阅perlreftut (符号和其他)。 See perldsc for help using data structures. 有关使用数据结构的帮助,请参阅perldsc See perlmod for more on typeglobs. 有关typeglobs的更多信息,请参阅perlmod See perlsub for more on lexical variables. 有关词汇变量的更多信息,请参阅perlsub

Here's an example of using locked hashes to control access to data based on the content of a variable: 以下是使用锁定哈希来控制基于变量内容的数据访问的示例:

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

All warnings aside, the syntax to use symbolic references should you need to use it (but you won't) is: 抛开所有警告,你需要使用符号引用的语法(但你不会):

use strict;
use warnings;

my $name = 'bob';

our @bob = qw/jerk genius/;

my $qualities;

{   no strict 'refs';
    print "$name: ", @$name, "\n";
    $qualities = \@$name;
}

print "$name is a @$qualities\n";  

Note that the array @bob is declared with our . 请注意,数组@bob是用our声明our Symbolic references only work with values in the symbol table. 符号引用仅适用于符号表中的值。 In other words, lexical variables do not work with symbolic references. 换句话说,词法变量不适用于符号引用。

Just in case I haven't emphasized this enough, don't use symbolic references . 如果我没有强调这一点, 请不要使用符号引用

This is very bad practice. 这是非常糟糕的做法。 If you ever need to do it, it means you should refactor your code. 如果需要做的,这意味着你应该重构你的代码。 Perhaps a hash with named keys would be better: 也许带有命名键的哈希会更好:

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

See perldoc -q "variable name" : 请参阅perldoc -q "variable name"

Beginners often think they want to have a variable contain the name of a variable. 初学者通常认为他们希望变量包含变量的名称。 ... ...

Short answer: Don't. 简答:不要。 Long answer: Read the FAQ entry (which is also available on your computer). 答案很长:阅读FAQ条目(也可在您的计算机上找到)。 Longer answer: Read MJD's Why it's stupid to "use a variable as a variable name" ( Part 2 , Part 3 ). 更长的答案:读MJD 为什么“将变量用作变量名称”是愚蠢的第2 部分第3部分 )。

You really shouldn't have to do this, see depesz's answer for the alternative, but... 你真的不应该这样做,看看depesz的替代方案的答案,但......

{
    no strict 'refs';
    print join(q{, }, @$name);
}

Yes, you can use a string scalar as a variable reference, and it looks up the variable by name. 是的,您可以使用字符串标量作为变量引用,并按名称查找变量。

You can also do this with typeglobs, see the Symbol module for an easy way. 您也可以使用typeglobs执行此操作,请参阅符号模块以获得简单的方法。

Usually when you think you need to use symbolic references, you will be better served by using a hash (associative array). 通常当您认为需要使用符号引用时,通过使用哈希(关联数组)可以更好地服务。

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

Results in: 结果是:

jerk perlfan
mary had a little lamb
susan not found

If you think you really need to use symbolic references, this is a safer way to do that. 如果您认为您确实需要使用符号引用,那么这是一种更安全的方法。

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

Which returns: 哪个回报:

jerk perlfan
# mary is not an array, it's a scalar
mary had a little lamb
susan not found

You should notice that it is harder to symbolic references safely, which is why you shouldn't use them. 您应该注意到安全的符号引用更难,这就是您不应该使用它们的原因。

Unless of course you are an expert doing something advanced. 除非你当然是专家做一些先进的事情。

no strict 'refs';
print "$name is @$name\n";

符号引用值得避免,但如果您真的想要使用它们,它们具有与常规引用相同的使用语法:请参阅http://perlmonks.org/?node=References+quick+reference

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM