Perl使用eval迭代列表名称

时间:2014-04-26 23:46:45

标签: arrays perl variables eval

为什么此代码无法正常运行?我试图编写代码来打印每个数组的最后一个值,看起来我只是用不同的变量名一遍又一遍地写相同的行。然后我尝试做这样的事情,我可以采取一个循环让它为我构建变量名称,然后评估它就像它是真正的Perl一样。但是当我尝试将它视为数组时,数组无法初始化并抛出错误。

现在,也许我对'eval'的使用感到困惑。但似乎这应该有效,而且我有点难过。我究竟做错了什么?我需要告诉perl评估“@a”(或者我所在的任何一个)并返回@a。

#!/usr/bin/perl -w                                                                                                                           
use strict;

my @a = (1, 2, 3);
my @b = (4, 5, 6);
my @c = (7, 8, 9);
my @letters = ('a'..'c');

foreach (@letters) {
    my $varname = '@' . "$_"; ## Generate the variable name I want to use. Returns '@a' or '@b' or '@c' just fine.
    my @foo = eval { $varname }; ## Only returns '@a' or '@b' or '@c' again.  =\
    foreach (@foo) {  
        print 'The last element of the array is: ' . $foo[-1] . "\n";  ## returns only the array name.  e.g. '@a' See previous comment.
    }
}

如果我没弄错的话,这个程序的正确输出应该是36912。

2 个答案:

答案 0 :(得分:2)

您需要eval $varname,而不是eval { $varname }

但请阅读Why it's stupid to `use a variable as a variable name'

最好是使用引用 - 例如:

#!/usr/bin/env perl
use strict;
use warnings;

my @a = (1, 2, 3);
my @b = (4, 5, 6);
my @c = (7, 8, 9);
my @all = (\@a, \@b, \@c);

foreach (@all) {
    my @foo = @$_;
    foreach (@foo) {
        print "The last element of the array is: $foo[-1]\n";
    }
}

答案 1 :(得分:0)

您可以通过阅读eval的文档来解释您的问题,因为您使用的是第二个表单而不是第一个表单:

  
      
  • eval EXPR
  •   
  • eval BLOCK
  •   
  • eval

         

    在第一种形式中,EXPR的返回值被解析并执行,好像它是一个小的Perl程序。首先解析表达式的值(它本身在标量上下文中确定),如果没有错误,则作为当前Perl程序的词汇上下文中的块执行。这意味着,特别是任何外部词法变量都是可见的,之后任何包变量设置或子例程和格式定义都会保留。

         

    ...

         

    在第二种形式中,BLOCK中的代码只被解析一次 - 同时解析eval本身周围的代码 - 并在当前Perl程序的上下文中执行。此表单通常用于比第一个表单更有效地捕获异常(见下文),同时还提供了在编译时检查BLOCK中的代码的好处。

  •   

基本上,my @foo = eval { $varname };等同于my @foo = do { $varname };,但它会进行错误捕获。显然,虚空上下文中的简单标量不会引发任何错误,因此它等同于my @foo = $varname;

如果你想要另一个,你必须使用my @foo = eval "$varname";

无论如何,你根本不应该使用eval。它不是初学者程序员必备的工具,只会让你遇到麻烦。 {@ 1}}初学者可接受的唯一时间是正则表达式的RHS,eval

因此,请遵循tobyink的建议并使用参考资料。