关于 Perl 地图函数的建议

Advice on Perl map function

我很难理解下面 Perl 脚本中 map 函数的行为

my @list = qw/A C T G/;
my @curr = (0, undef, undef, 1);
my @res = map { $list[ $_ ] } @curr;
print @res; #prints AAAC

@res的值为AAAC。我原以为它只是 AC 因为 @curr 的 2 个中间值是 undef.

我对map的理解是list中的每一项依次成为$_的值。所以我可以理解 $list[0] returns A 和 $list[1] returns C。我无法理解 why/how undef 值返回了 A ?在我看来 $list[undef] 不是一个值?

我可能遗漏了一些明显的东西,但非常感谢您的帮助

我从中获取此代码的脚本如下。我在调试器中逐步执行它,我可以在 sub gen_permutate

返回的最后一行中看到这种行为
my @DNA = qw/A C T G/;
my $seq = gen_permutate(14, @DNA);

while ( my $strand = $seq->() ) {
print "$strand\n";

}

sub gen_permutate {
    my ($max, @list) = @_;
    my @curr;
    
    return sub {
        if ( (join '', map { $list[ $_ ] } @curr) eq $list[ -1 ] x @curr ) {
            @curr = (0) x (@curr + 1);
        else {
            my $pos = @curr; 
            while ( --$pos > -1 ) {
                ++$curr[ $pos ], last if $curr[ $pos ] < $#list; 
                $curr[ $pos ] = 0;
            }
        }
        return undef if @curr > $max;
        return join '', map { $list[ $_ ] } @curr; 
    };
}

J

我想回答我自己的问题,undef 有时被视为零。这就是 $list[undef] 与 $list[0]

相同的原因

这是“DWIM”的一部分——数组索引需要是一个数字,因此传入的内容将转换为一个,尽解释器所能做到的最好do/guess。在 undef 的情况下至少很清楚——变成了 0.

但这确实是一个编程错误,或者至少是草率。

做你期望的事:

my @res = map { $list[ $_ ] } grep { defined } @curr;

或者,在列表的一次迭代中

my @res = map { defined $_ ? $list[$_] : () } @curr;

此处由 () 表示的空列表被压平到 return 列表中,从而消失;所以我们也在 map 内部进行过滤。但是那个三元组的要点是能够代替有意义的东西,如果需要删除一些输入,那么先有一个明确的 grep 会更清楚。

注意 有了 use warnings; 你会听到所有关于它的信息

Use of uninitialized value $_ in array element at ...

(并将其转换为数字)

每个脚本确实必须use warnings;(和use strict;)开头。有时继承旧脚本的最大部分是立即将 use warnings; 放在最上面(并处理满屏的消息 :(.