在我编写的代码中,我使用hash-ref将数据传递给方法(参见注释[1])。
遗憾的是,这导致了许多重复的代码:
sub thing {
my ($self, $params) = @_;
my ($foo, $bar, $baz, $biff,);
if ( exists $params->{foo} && $params->{foo} ) {
$foo = $params->{foo};
}
# repeat for `bar`, `baz`, `biff`
## rest of function ##
}
(并在每个带参数的函数中重复)
更容易定义参数列表,然后 迭代该列表,创建两个变量并在需要时将它们设置为值。
为了测试这个,我试过了:
my $params = { x => 1, y => 2};
my @params = qw(x y z a b c);
gno strict 'refs';
rep( ${$_}, @params );
use strict 'refs';
foreach my $p (@params) {
if ( exists $params->{$p} && $params->{$p} ) {
${$p} = $params->{$p};
}
}
print "x:$x, y:$y, z:$z, a:$a, b:$b, c:$c\n"
这给了我以下错误:
Global symbol "$x" requires explicit package name at ./test.pl line 20.
Global symbol "$y" requires explicit package name at ./test.pl line 20.
Global symbol "$z" requires explicit package name at ./test.pl line 20.
Global symbol "$c" requires explicit package name at ./test.pl line 20.
我可以做这个动态变量创建吗? (如果是的话,怎么样?)
[1]通过使用哈希来传递数据,我在很多方面获益:
undef
值答案 0 :(得分:5)
是的,您可以在Perl中执行此操作。但对于Mark Dominus在these three articles中解释的所有原因,这是一个可怕的想法。
将这些值存储在哈希中是一个好主意。
#!/usr/bin/perl
use strict;
use warnings;
my $params = { x => 1, y => 2};
my @params = qw(x y z a b c);
my %var;
foreach my $p (@params) {
# You need to take care exactly what you want in this
# logical statement. The options are:
# 1/ $p exists in the hash
# exists $params->{$p}
# 2/ $p exists in the hash and has a defined value
# defined $params->{$p}
# 3/ $p exists in the hash and has a true value
# $params->{$p}
# I think the first option is most likely. The last one has
# good chance of introducing subtle bugs.
if ( exists $params->{$p} ) {
$var{$p} = $params->{$p};
}
}
print join ', ', map { "$_: " . ($var{$_} // 'undef') } @params;
print "\n";
答案 1 :(得分:1)
使用像这样的符号引用是一个非常糟糕的主意...哈希很好地完全消除了对此的需求。
use warnings;
use strict;
my $params = { x => 1, y => 2, foo => 3, };
thing($params);
sub thing {
my $params = shift;
my $foo;
if (defined $params->{foo}){
$foo = $params->{foo};
}
print $foo;
}
您也可以直接传入哈希本身(无论是预先创建的,还是内联传递给子。如果预先创建,则子将在副本上运行。)
thing(foo => 1, x => 2);
sub thing {
my %params = @_;
print $params{foo} if defined $params{foo};
}
答案 2 :(得分:1)
感谢Dave Cross&其他 - 以下测试工作:
#!/usr/bin/perl
use strict;
use warnings;
use English qw( -no_match_vars ) ;
use Carp;
use Data::Dumper;
my $params = { x => 1, y => 2, z => 0};
my @params = qw(x y z a b c);
my %var;
foreach my $p (@params) {
if ( exists $params->{$p} ) {
$var{$p} = $params->{$p};
} else {
$var{$p} = undef;
}
}
print Dumper \%var;
这为我%var
提供了所有需要的参数(如@params
中所列,其中未传入的参数(即,不在$params
hashref中)创建了{ {1}}值。
因此,我可以放心地测试值和真理,而不必担心存在。
谢谢大家。
答案 3 :(得分:0)
我使用软参考做了这个:
#!perl
no strict "refs";
my %vars = ( x => 1, y => 2 );
for my $k ( keys %vars ) {
$$k = $vars{$k};
}
print $x, $y;
但推荐设置(使用严格;使用警告;)可以防止出现这种模式。用它来拍脚很容易。
答案 4 :(得分:0)
perl -Mstrict -MData::Dumper -wE'
{package Data::Dumper;our($Indent,$Sortkeys,$Terse,$Useqq)=(1)x4}
my @aok = qw( x y z a b c );
my %dft = ( a => -1 );
say "- - - -";
my $arg = { x => 1, y => 2, foo => 42 };
$arg = { %dft, %$arg };
say "arg: ", Dumper($arg);
my %var;
@var{ @aok } = @$arg{ @aok };
say "var: ", Dumper(\%var);
my %aok = map { $_ => 1 } @aok;
my @huh = grep !$aok{$_}, sort keys %$arg;
@huh and say "huh: ", Dumper(\@huh);
'
- - - -
arg: {
"a" => -1,
"foo" => 42,
"x" => 1,
"y" => 2
}
var: {
"a" => -1,
"b" => undef,
"c" => undef,
"x" => 1,
"y" => 2,
"z" => undef
}
huh: [
"foo"
]