【问题标题】:In Perl, can refer to an array using its name?在 Perl 中,可以使用数组名来引用数组吗?
【发布时间】:2011-10-28 05:02:54
【问题描述】:

我是 Perl 新手,我知道您可以按名称调用函数,如下所示: &$functionName();。但是,我想按名称使用数组。这可能吗?

长代码:

sub print_species_names {
    my $species = shift(@_);
    my @cats = ("Jeffry", "Owen");
    my @dogs = ("Duke", "Lassie");

    switch ($species) {
        case "cats" {
            foreach (@cats) {
                print $_ . "\n";
            }
        }
        case "dogs" {
            foreach (@dogs) {
                print $_ . "\n";
            }
        }
    }
}

寻求类似这样的短代码:

sub print_species_names {
    my $species = shift(@_);
    my @cats = ("Jeffry", "Owen");
    my @dogs = ("Duke", "Lassie");

    foreach (@<$species>) {
        print $_ . "\n";
    }
}

【问题讨论】:

标签: perl symbolic-references


【解决方案1】:

可能吗?是的。推荐的? 。一般来说,使用符号引用是不好的做法。相反,使用散列来保存您的数组。这样您就可以按名称查找它们:

sub print_species_names {
    my $species = shift;
    my %animals = (
        cats => [qw(Jeffry Owen)],
        dogs => [qw(Duke Lassie)],
    );
    if (my $array = $animals{$species}) {
        print "$_\n" for @$array
    }
    else {
        die "species '$species' not found"
    }
}

如果您想进一步减少,可以将 if/else 块替换为:

    print "$_\n" for @{ $animals{$species}
        or die "species $species not found" };

【讨论】:

  • 啊,使用符号引用还不错……使 perl 中的元编程成为可能。
【解决方案2】:

您可以通过使用数组引用的哈希来实现接近的目标:

%hash = ( 'cats' => [ "Jeffry", "Owen"],
          'dogs' => [ "Duke", "Lassie" ] );

$arrayRef = $hash{cats};

【讨论】:

    【解决方案3】:

    你也可以在这里使用 eval:

    foreach (eval("@$species")) {
            print $_ . "\n";
        }
    

    我应该明确表示您需要关闭严格的引用才能使其正常工作。因此,使用“nostrict”围绕代码并使用“strict”可以正常工作。

    这就是 perl 中所谓的软引用。

    【讨论】:

    • Can't use string ("whatever was in $species") as an ARRAY ref while "strict refs" in use at ... 你的意思可能是\@$species 但是,不要推荐字符串eval 用于这样的事情。如果你这样做了,至少要检查错误。
    • @ennukiller,eval 如果使用正确,则在这种情况下绕过严格,如果您关闭严格,则可以使用使用 foreach (@$species)) { ... } 并绕过 eval
    • strict 在这里发现了一个重要错误。如果您关闭严格,则会发生以下转换:"@$species" -&gt; "@main::dogs" -&gt; '' -&gt; eval('') -&gt; '' 这将默默地无法执行 OP 想要的操作,因为变量是词法的。如果 OP 然后切换到包变量,情况会变得更糟。 "@$species" -&gt; "@main::dogs" -&gt; 'Duke Lassie' -&gt; eval('Duke Lassie') -&gt; tries to call Lassie-&gt;Duke() and hopefully fails -&gt; ''。正如我在第一条评论中所说,您可能想要 eval('@'.$species) 这会起作用,但这一切都强调了为什么您不应该这样做。
    猜你喜欢
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 2012-04-09
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2016-02-25
    相关资源
    最近更新 更多