我创建了一个子函数,它返回对包含7-8个变量的属性哈希的引用。每当我想访问一个元素时,我要么重新定义它my $n_players = $ref_attr->{'n_players'}
,要么直接调用它$ref_attr->{'n_players'}
。我宁愿使用所有重新定义的变量(第一种情况)但是这需要7-8行初始化并使我的代码混乱。
是否有一个模块(我似乎无法找到)或导出哈希键用作变量的好方法?
答案 0 :(得分:8)
您可以使用hash slices来减少从哈希中获取多个条目所涉及的重复次数。例如,您可以在初始化副本时使用此功能(假设您还有n_teams
条目):
my ($n_players, $n_teams) = @$ref_attr{qw( n_players n_teams )};
正如Eric Strom建议的那样,您还可以使用缩进来帮助确保按正确的顺序获得密钥:
my ($n_players, $n_teams) = @$ref_attr{
qw( n_players n_teams)
};
正如其他人所说,可以操纵符号表来创建与每个键对应的变量,但这不是一个好主意。
答案 1 :(得分:5)
您可以使用引用和哈希切片轻松完成此操作:
sub takes_hashref {
my $hashref = shift;
my ($one, $two, $three, $four, $five) = \@$hashref{
qw(one two three four five)
};
print "one: $$one, two: $$two, three: $$three, ",
"four: $$four, five: $$five\n";
$_++ for $$one, $$three, $$five;
}
my %hash = qw(one 1 two 2 three 3 four 4 five 5);
takes_hashref \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
@$hashref{qw(x y z)}
是一个哈希切片,它返回一个值列表。前置\
接受每个值的引用并返回引用列表。然后将其分配给词法变量。当您使用每个变量时,将该符号加倍以取消引用它:$$var
。由于这些变量包含对哈希字段的引用,因此您可以为它们分配:$$var = 'new val'
,并且赋值将更改原始哈希。如果您不关心传播回哈希值的变量的更改,则可以省略哈希切片上的\
,以及所有变量上的双重符号。
如果您只想创建一个较短的别名,可以在子资源中本地化%_
:
sub takes_hashref2 {
my $hashref = shift;
local *_ = \%$hashref;
print "one: $_{one}, two: $_{two}, three: $_{three}, ",
"four: $_{four}, five: $_{five}\n";
$_++ for @_{qw(one three five)};
}
my %hash = qw(one 1 two 2 three 3 four 4 five 5);
takes_hashref2 \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref2 \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref2 \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
行local *_ = \%$hashref
将%_
别名为$hashref
中的哈希值。 \%
部分不是必需的,但如果$hashref
中的值不是哈希,则会抛出错误。它只是一种较短的写作方式:
die 'not a hash' unless ref $hashref eq 'HASH';
local *_ = $hashref;
你可以把它写成一行:
local *_ = \%{shift @_};
答案 2 :(得分:3)
别。要么明确地复制它们(你的第一个选项),要么只使用哈希(你的第二个选项)。从长远来看,这是非常清楚的。
...
但是如果你真的想,那么哈希%::是你当前的包变量hash(是的,perl internals)。你可以玩它。
perl -e'print %::';
答案 3 :(得分:3)
我是哈曼的第二个建议(不要),但如果你想要它的话:
my %vars = ( a => 1, b => 2 );
while (my ($k,$v) = each %vars) {
$::{$k} = \$v;
}
print "a=$a, b=$b\n";
答案 4 :(得分:0)
另一种选择是为您的数据集合创建一个类,并让子函数返回该类的实例(对象)而不是普通的hashref。然后,您将访问值$returned_object->n_players
。在这种特殊情况下,它在保存的打字方面或者与$ref_attr->{n_players}
相比没有真正为你带来太多的购买,但是去OOP开辟了很多可能性(例如,只读或计算属性)随着您的计划不断发展,或者未来证明有用。