当我运行这样一段简单的代码时:
my @arr=(1..5);
my $x;
foreach $x (@arr) {
$x+=10;
}
print "@arr";
结果是“11 12 13 14 15”,因为$ x“变成”foreach中@arr数组中的每个元素。够了。
但这是我的事情......不是一个问题(解决方案很简单,但不优雅,我希望我的perl尽可能优雅)。
我写了一个用于处理COBOL数据的tie模块。它需要一个副本,解析字段,然后将其附加到标量/字符串,以便访问/来自绑定的散列将返回/设置字符串中的值。它运作得非常好。
my %h,$rec;
my $cb=<<END;
01 CH-RECORD.
05 JOB-NUM PIC X.
05 FILLER PIC X(76).
05 REC-TYPE PIC X(2).
END
tie %h, 'COBOLDataTie',$cb,\$rec; #tie the hash to the record via the copybook
从那里,我可以将COBOL记录移动到$ rec并使用%h哈希访问COBOL字段。
同样,这完美无缺。但问题来自于我想要迭代一堆COBOL记录。因此,如果在上面的代码之后我有类似的东西:
foreach $rec (@arr) {
print "Job is ",$h{'JOB-NUM'},"\n";
}
它不起作用,因为foreach实际上改变了$ rec的位置,这打破了它的关系。我最终不得不做这样的事情:
foreach (@arr) {
$rec=$_;
print "Job is ",$h{'JOB-NUM'},"\n";
}
我有什么方法可以做“foreach $ rec(@arr)”而不是打破我的捆绑哈希?
(在任何人说之前,是的,我知道这需要一个很好的面向对象的解决方案......有一天我会做到这一点;我只需要先找一些时间)
EPILOGUE:我修改了TieHash代码,而不是指向外部记录,它截取哈希的“特殊”键,其中包括“记录”。因此,当我将记录字符串分配给$ h {'record'}时,它与上面示例中的加载$ rec相同。这是一个更好的解决方案,更加独立。它还暴露出更像OOP的界面。
答案 0 :(得分:2)
您决定创建的界面是“分配到$rec
,然后通过%h
”访问字段。因此,这正是您需要做的。
for (@arr) {
$rec = $_;
print "Job is $h{'JOB-NUM'}\n";
}
当然看起来很奇怪,但那是因为它很奇怪。这会更合理:
for (@arr) {
my $h = parse($cb, $_);
print "Job is $h->{'JOB-NUM'}\n";
}
你甚至可以用最小的改变来做到这一点:
sub parse {
my ($cb, $rec) = @_;
tie my %h, 'COBOLDataTie', $cb, \$rec;
return \%h;
}
答案 1 :(得分:2)
这是一个微妙的点,在文档中很容易被忽略,但foreach
变量中的循环变量始终是一个新变量,与任何名称相同的词汇或包变量无关否则在程序中。
来自perlsyn
:
Foreach循环
“foreach”循环遍历正常列表值并设置 变量VAR依次是列表的每个元素。如果变量 之前是关键字“my”,然后它是词法范围的,并且是 因此仅在循环内可见。否则,变量是 隐含地循环本地并在退出时重新获得其原值 循环。如果变量先前使用“my”声明,则使用 该变量而不是全局变量,但它仍然是本地化的 循环。这种隐式本地化只发生在“foreach”循环中。
(重点补充)。也就是说,这个小脚本第3行中的$rec
与第1行中声明的$rec
无关
1: my $rec = 'foo';
2: print $rec; # 'foo'
3: foreach $rec (@some_list) {
4: print $rec; # something else
5: }
6: print $rec; # 'foo' again
因此,如果您想使用\$rec
来影响绑定哈希的行为(尽管还有其他方法可以做到这一点),那么您正在做正确的事情来使用不同的循环变量并分配{{ 1}}在循环内部。
答案 2 :(得分:0)
似乎最好的方法是做一些事情:
for (my $i=0;($rec=$arr[$i], $i<@arr);$i++) {
不完全是我希望的优雅,但似乎有效。