Perl 例程作为参数--泛型变量不起作用
我正在编写一个游戏系统(战争游戏等),并正在创建创建和显示十六进制地图的系统。我很快意识到我正在重复执行一个x=(0..maxx)和y=(0..maxy)的嵌套循环。因此,我试图修改我在某处找到的一些代码(高级perl书籍之一,我忘了在哪里了),以创建一种更简单的方法来完成这种循环。这就是我想到的:Perl 例程作为参数--泛型变量不起作用,perl,Perl,我正在编写一个游戏系统(战争游戏等),并正在创建创建和显示十六进制地图的系统。我很快意识到我正在重复执行一个x=(0..maxx)和y=(0..maxy)的嵌套循环。因此,我试图修改我在某处找到的一些代码(高级perl书籍之一,我忘了在哪里了),以创建一种更简单的方法来完成这种循环。这就是我想到的: sub fillmap (&@) { my $code = shift; no strict 'refs'; use vars qw($x $y); my $
sub fillmap (&@) {
my $code = shift;
no strict 'refs';
use vars qw($x $y);
my $caller = caller;
local(*{$caller."::x"}) = \my $x;
local(*{$caller."::y"}) = \my $y;
foreach $x (0..5) {
foreach $y (0..3) {
warn "fillmap $x,$y\n";
&{$code}($x,$y);
}
}
}
假设它的工作方式类似于排序,但是使用$x
和$y
而不是$a
和$b
注意:warn语句用于调试。我还简化了x和y范围(传入的数组确定了maxx和maxy值,但我不想让讨论与计算它们的例程混淆…我只是将它们硬编码为maxx=5和maxy=3)
所以,这个例程的执行是这样的:
fillmap {warn "$x,$y\n";} @map;
应该产生一个x,y对的列表。但相反,它给了我这个:
fillmap 0,0
,
fillmap 0,1
,
fillmap 0,2
,
fillmap 0,3
,
fillmap 1,0
,
...
注意,“fillmap”行来自用于调试的子例程。但不是每个x,y对,而是逗号($x和$y未定义)
我做错了什么?问题是,
for$x
本身就有本地化功能。循环中的$x
不是别名为$caller::x
的$x
您需要执行以下操作之一:
- 将
复制到循环中的$x
$caller::x
- 循环内的别名
到$caller::x
$x
use strict;
use warnings;
sub fillmap(&@) {
my $code = shift;
my $caller = caller();
my $xp = do { no strict 'refs'; \*{$caller.'::x'} }; local *$xp;
my $yp = do { no strict 'refs'; \*{$caller.'::y'} }; local *$yp;
for my $x (0..1) {
*$xp = \$x;
for my $y (0..2) {
*$yp = \$y;
$code->();
}
}
}
our ($x, $y);
fillmap { warn "$x,$y\n"; } '...';
您可以避免使用
我们的($x,$y)代码>使用$a
和$b
而不是$x
和$y
。您无法通过将它(或使用vars qw($x$y);
移动到fillmap
中来解决问题,因为您显然希望fillmap
用于与调用方不同的包和词法范围。(我使用$caller::x
作为${caller()::x}fillmap(&@)
应该是fillmap(&\@)
设置$caller::x
并将$x
作为参数传递是多余的。我解开了一个。我想对你的解决方案做一些额外的解释。。。它就像一个冠军,但复制粘贴代码并不能教会我很多东西:-)哪一部分?我添加的唯一元素是我更改了*caller::x=\$x
到*{\*调用方::x}=\$x
这样我就可以把它分成两条语句($xp=\*$caller::x;*$xp=\$x;
)。这只是一种引用尊重,就像@{\@a}
与@a
一样。