例程作为参数--泛型变量不起作用



我正在编写一个游戏系统(战争游戏等),并正在创建用于创建和显示十六进制地图的系统。我很快意识到,我正在重复执行x=(0.maxx)和y=(0..maxy)的嵌套循环。因此,我试图调整我在某个地方找到的一些代码(我忘记了在哪里),以创建一种更容易的方式来进行这种循环。这就是我想到的:

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,$yn";
            &{$code}($x,$y);
        }
    }
}

假设它的工作方式与sort类似,但使用$x$y而不是$a$b

注意:warn语句用于调试。我还简化了x和y范围(传入的数组确定了maxx和maxy值,但我不想用计算它们的例程来搅乱讨论……我只是将它们硬编码为maxx=5和maxy=3)

所以,这个例程的执行是这样的:

fillmap {warn "$x,$yn";} @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,$yn"; } '...';

使用$a$b代替$x$y可以避免对our ($x, $y);的需要。您无法通过将它(或use vars qw( $x $y );)移动到fillmap来解决问题,因为您显然希望fillmap在与调用者不同的包和词法范围中使用。

最新更新