所以这个问题纯粹是出于学习目的和好奇心,但任何人都可以解释下面的功能如何运作?
sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {
my $max = -1;
$max < $#$_ && ( $max = $#$_ ) foreach @_;
map {
my $ix = $_;
map $_->[$ix], @_;
} 0 .. $max;
}
来自List::MoreUtils模块。我在我的一个应用程序中使用它,我碰巧看到了源代码,这让我觉得我根本不懂perl!任何人都可以解释这种疯狂吗? :)谢谢!
答案 0 :(得分:13)
我不会覆盖原型部分(暴徒说他会)。
这是一个更易阅读的版本 - 理想情况下,它应该是自我解释的
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 < / em>的)
......从技术上讲,它们不需要被命名,只需要取消引用。例如@$ref
和@{[qw( foo bar )]}
与@a
一样有效。换句话说,它必须以@
开头(而不是切片)。 (池上)
换句话说,以下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)作为参数传递给与内置函数类似的函数(例如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.