假设我有一个实用程序库(other
)包含子程序
(sort_it
)我想用它来返回任意排序的数据。
它可能比这更复杂,但这说明了
关键概念:
#!/usr/local/bin/perl
use strict;
package other;
sub sort_it {
my($data, $sort_function) = @_;
return([sort $sort_function @$data]);
}
现在让我们在另一个包中使用它。
package main;
use Data::Dumper;
my($data) = [
{'animal' => 'bird', 'legs' => 2},
{'animal' => 'black widow', 'legs' => 8},
{'animal' => 'dog', 'legs' => 4},
{'animal' => 'grasshopper', 'legs' => 6},
{'animal' => 'human', 'legs' => 2},
{'animal' => 'mosquito', 'legs' => 6},
{'animal' => 'rhino', 'legs' => 4},
{'animal' => 'tarantula', 'legs' => 8},
{'animal' => 'tiger', 'legs' => 4},
],
my($sort_by_legs_then_name) = sub {
return ($a->{'legs'} <=> $b->{'legs'} ||
$a->{'animal'} cmp $b->{'animal'});
};
print Dumper(other::sort_it($data, $sort_by_legs_then_name));
由于一个微妙的问题,这不起作用。 $a
和 $b
是包
全局。他们指的是 $main::a
和 $main::b
什么时候被包裹起来
关闭。
我们可以通过说,而不是:
my($sort_by_legs_then_name) = sub {
return ($other::a->{'legs'} <=> $other::b->{'legs'} ||
$other::a->{'animal'} cmp $other::b->{'animal'});
};
这有效,但迫使我们硬编码实用程序包的名称
到处。如果要改变,我们需要记住改变
代码,而不仅仅是 use other qw(sort_it);
声明很可能
出现在现实世界中。
您可能会立即考虑尝试使用 __PACKAGE__
。那风
评估为“主要”。那样做 eval("__PACKAGE__");
。
有一个技巧使用 caller
这样可行:
my($sort_by_legs_then_name) = sub {
my($context) = [caller(0)]->[0];
my($a) = eval("\$$context" . "::a");
my($b) = eval("\$$context" . "::b");
return ($a->{'legs'} <=> $b->{'legs'} ||
$a->{'animal'} cmp $b->{'animal'});
};
但这是相当黑魔法的。好像应该有 一些更好的解决方案。但我还没有找到或想出来 出来了。