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 $

我正在编写一个游戏系统(战争游戏等),并正在创建创建和显示十六进制地图的系统。我很快意识到我正在重复执行一个x=(0..maxx)和y=(0..maxy)的嵌套循环。因此,我试图修改我在某处找到的一些代码(高级perl书籍之一,我忘了在哪里了),以创建一种更简单的方法来完成这种循环。这就是我想到的:

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
一样。