perl - List::MoreUtils 网格或者'zip'函数

  显示原文与译文双语对照的内容
0 0

所以这个问题纯属好奇,但是为了学习的目的,谁能解释下这个函数是如何工作的?

sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) {
    my $max = -1;
    $max < $#$_ && ( $max = $#$_ ) foreach @_;
    map {
        my $ix = $_;
        map $_->[$ix], @_;
    } 0 .. $max;
}

这是来自 List::MoreUtils 模块。 我在我的一个应用程序中使用它,我碰巧看到源代码,这让我觉得我根本不知道perl ! 谁能解释一下这疯狂? = = = = = 谢谢 !

时间:原作者:1个回答

0 0

我并没有讲到原型的( mob说他将一部分) 。

这是理想情况下,可读性更强的版本应该意义明确

sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) {
    # Calculate the maximum number of elements in each of the array refs 
    # we were passed:
    my $maxLength = 0;
    foreach my $array_ref (@_) { # @_ is all arrey refs passed in
        if ($maxLength < @$array_ref) { 
            # we found an array longer than all previous ones 
            $maxLength = @$array_ref;
        }
    }
    # If you represent the arrays as a matrix:
    #   ARR1 = [ a1e1, a1e2, .... a1eN],
    #   ARR2 = [ a2e1, a2e2, .... a2eN],
    #    ...
    #   ARR2 = [ aMe1, aMe2, .... aMeN];
    # Then, we are simply walking through the matrix;
    # each column top to bottom then move on to next column left to right
    # (a1e1, a2e1, ... aMe1, a1e2, a2e2, ... aMeN)
    my @results;
    for (my $index = 0; $index < $maxLength; $index++) { # Iterate over columns
         foreach my $array_ref (@_) { # Iterate over per-row cells in each column
             push @results, $array_ref->[$index];
         }
    } ;
}

这是一个已注释的原始版本

sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) {
    # Calculate the largest index in each of the array refs
    # @_ is an array of all the input arrayrefs
    # $_ will be one of the array refs in a foreach loop
    # $#{$X} is the largest index in arrayref X; thus
    # $#$_ is the largest index in arrayref $_
    my $max = -1;
    $max < $#$_ && ( $max = $#$_ ) foreach @_;
    # Return a list, obtained by looping 
    # over every index from 0 to the maximal index of any of the arrays
    # Then, for each value of the index ($ix), push into the resulting list
    # an element with that index from each of the arrays.
    map {
        my $ix = $_;
        map $_->[$ix], @_;
    } 0 .. $max;
}


其中一个不寻常的东西在此方法function signature (prototype)

sub mesh (@@;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@) {

作为@mob和@ikegami明智地加以说明注释,

。。。 则指示Perl在预期介于2 和32中名为数组,并将它们传递到函数( @_ ) 作为数组引用。 所以如果你调用 mesh @a,@b,@c,那么 @_在网格设置为 (@a,@b,@c)而不是一个" 平面" 列表包含所有的单个元素 @a, @b, and @c( mob )
。。。 他们技术上不需要命名,只要取消引用。 e .g 。 @$ref@{[qw( foo bar )]}工作一样好 @a. 换句话说,这得归功于 @( 而且不是切片) 。 ( ikegami )

换句话说,下面的2 调用行为一样

my @a1 = (1);
my @a2 = (2);
sub mesh_prototype(@@) { print "$_->[0]n" }
sub mesh_pass_arrayref() { print "$_->[0]n" }
mesh_prototype(@a1, @a2);
mesh_pass_arrayref(@a1, @a2);

这样做是,以便你可以传递单个数组( 而不是arrayrefs ) 作为参数传递给函数,这些函数将像ins ( e .g构建。 map/ sort)

回答Zaid查询为那么,如果1 或33列出了数组作为参数来调用, mesh(),它会生成一个编译时错误:

Not enough arguments for main::mesh at mesh.pl line 16, near "@a1)"
Execution of mesh.pl aborted due to compilation errors.
Too many arguments for main::mesh at mesh.pl line 16, near "@a2)"
Execution of mesh.pl aborted due to compilation errors.
原作者:
...