我怎样才能避免在 Perl 中使用"eval"?

  • 本文关键字:eval Perl 能避免 perl eval
  • 更新时间 :
  • 英文 :


我有这样的代码:

my @e = ( '($i,$j, $k,$l)',  '($i,$k, $j,$l)',  '($i,$l, $j,$k)',
'($j,$k, $i,$l)',  '($j,$l, $i,$k)',  '($k,$l, $i,$j)'
);
#
# Assign various sets of values to $i,$j,$k,$l
#
foreach ( @e ) {
my ($a,$b, $c,$d) = eval $_;
#
# Do calculations based on the values of $a,$b,$c,$d
#

一切都如我所愿。但这样使用eval感觉很笨拙。我觉得必须有一种更好的方法来循环这四个值的六个排列。我尝试了各种方法,但都没有找到有效的方法,所以我放弃了使用eval。

我可能会选择subs。

my @e = (
sub { @_[ 0,1, 2,3 ] },
sub { @_[ 0,2, 1,3 ] },
sub { @_[ 0,3, 1,2 ] },
sub { @_[ 1,2, 0,3 ] },
sub { @_[ 1,3, 0,2 ] },
sub { @_[ 2,3, 0,1 ] },
);
...
for (@e) {
my ( $a,$b, $c,$d ) = $_->($i, $j, $k, $l);
...
}

如果值已经在一个数组中,则以上简化为以下内容:

my @e = (
[ 0,1, 2,3 ],
[ 0,2, 1,3 ],
[ 0,3, 1,2 ],
[ 1,2, 0,3 ],
[ 1,3, 0,2 ],
[ 2,3, 0,1 ],
);
...
for (@e) {
my ( $a,$b, $c,$d ) = @v[$_];
...
}

如果我们要处理更多的值,我会考虑一种程序化的方法来生成突变,但我想不出有价值的简单方法。

不要重新发明轮子。要循环遍历数组的所有排列,请使用为此目的编写的任何Perl模块,例如Algorithm::Permute(Håkon Hægland在评论中指出了这一点(。

例如:

use Algorithm::Permute;
use feature qw( say );
my $perm = new Algorithm::Permute([$i, $j, $k, $l]);
while (@permutation = $perm->next) {
say join "t", @permutation;
}

我不知道你到底想实现什么,但这可能会对你有所帮助:

my @e = ( [$i,$j, $k,$l],  [$i,$k, $j,$l],  [$i,$l, $j,$k],
[$j,$k, $i,$l],  [$j,$l, $i,$k],  [$k,$l, $i,$j]
);
...
foreach (@e) {
my ($a,$b, $c,$d) = @$_;
...

@e现在是数组引用的数组。在foreach循环中,$_始终包含一个数组引用,而@$_取消引用它,从而生成数组。

这具有略微不同的语义,因为当分配@e时,$i$j$k$l将仅被评估一次。这可能没问题,但在您的应用程序中可能会出现问题。

如果你需要你的原始行为,你可以使用一个稍微复杂一点的解决方案:

my @e = ( [$i,$j, $k,$l],  [$i,$k, $j,$l],  [$i,$l, $j,$k],
[$j,$k, $i,$l],  [$j,$l, $i,$k],  [$k,$l, $i,$j]
);
...
foreach (@e) {
my ($a,$b, $c,$d) = map {$$_} @$_;
...

这意味着,@e保持对变量的引用,并且它们将被map {$$_}取消引用。

顺便说一句,你应该考虑用前臂的身体做一个小循环。

我似乎能够从注释中了解到,$i $j $k $l的值在foreach循环期间会发生变化,您需要使用它们的当前值。这就是eval()解决方案有些疯狂的原因。

其他人提出了你没有接受的解决方案,所以这可能是你需要的。正如多纳特在回答中所说,你可以做一个前臂环的子集。通过这种方式,您可以在@e数组中不使用中间存储的情况下运行foreach循环。当然,这将依赖于改变子内部的全局变量,这通常是一件坏事。

do_foreach($i, $j, $k, $l);
do_foreach($i, $k, $j, $l);
do_foreach($i, $l, $j, $k);
...etc
sub do_foreach {
my ($a, $b, $c, $d) = @_;
... do stuff
}

我怀疑您的问题来自于代码中其他地方的糟糕设计决策,否则它可能会从解决中受益。但根据所提供的信息很难判断。

如果您确实只想处理样本代码中引用的排列,那么为什么不按以下方式处理呢(排列的平方数(?

注意:请详细说明您的问题,以及可以运行的白色最小代码示例(不要忘记use strict; use warnings——两行魔术,有助于避免许多陷阱(

use strict;
use warnings;
use feature 'say';
my($i,$j,$k,$l) = (1..4);
my @e = ( [$i,$j, $k,$l],  [$i,$k, $j,$l],  [$i,$l, $j,$k],
[$j,$k, $i,$l],  [$j,$l, $i,$k],  [$k,$l, $i,$j]
);

do_work($_) for @e;
sub do_work {
my $aref = shift;

my @square = map { $_*$_ } @{$aref};

say join "t", @square;
}

输出

1       4       9       16
1       9       4       16
1       16      4       9
4       9       1       16
4       16      1       9
9       16      1       4

我不知道为什么只有6个排列。请研究以下代码以符合您的问题。

use strict;
use warnings;
use feature 'say';
my @array = qw/a b c d/;
my $result = mutate(@array);
say join "t", @{$_} for @{$result};
sub mutate {
my $aref = shift;
my @data = @{$aref};
my @ret;

for ( 1..scalar @data ) {
my($c,@block) = @data;
for ( 1..scalar @block ) {
push @ret,[$c,@block];
my $t = pop @block;
unshift @block, $t;
}
@data = (@block,$c);
}

return @ret;
}

输出

a       b       c       d
a       d       b       c
a       c       d       b
b       c       d       a
b       a       c       d
b       d       a       c
c       d       a       b
c       b       d       a
c       a       b       d
d       a       b       c
d       c       a       b
d       b       c       a

my @array = qw/a b c d e/;的其他样品

a       b       c       d       e
a       e       b       c       d
a       d       e       b       c
a       c       d       e       b
b       c       d       e       a
b       a       c       d       e
b       e       a       c       d
b       d       e       a       c
c       d       e       a       b
c       b       d       e       a
c       a       b       d       e
c       e       a       b       d
d       e       a       b       c
d       c       e       a       b
d       b       c       e       a
d       a       b       c       e
e       a       b       c       d
e       d       a       b       c
e       c       d       a       b
e       b       c       d       a

相关内容

  • 没有找到相关文章

最新更新