我不會涵蓋原型部分(暴徒說他會)。
這裏有一個更可讀的版本 - 理想情況下,它應該是不言而喻的
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在評論中指出的明智,
... It instructs Perl to expect between 2 and 32 named arrays, and to pass them to the function (in @_) as array references. So if you call mesh @a,@b,@c
, then @_
in mesh is set to (\@a,\@b,\@c)
rather than one "flat" list with all the individual elements of @a, @b, and @c
(mob)
... They technically don't need to be named, just dereferenced. e.g. @$ref
and @{[qw(foo bar)]}
work just as well as @a
. In other words, it has to start with @
(and not be a slice). (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)作爲參數傳遞給表現得像內置插件的函數(例如,map
/sort
)
要回答扎伊德的查詢,這就是如果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.
我將介紹原型部分:-)。它指示Perl期望2到32個*命名數組*,並將它們作爲數組引用傳遞給函數(在@ _'中)。所以如果你調用'mesh @ a,@ b,@ c','mesh'中的'@ _'設置爲'(\ @a,\ @ b,\ @ c)',而不是一個「flat」列表, '@ a','@ b'和'@ c'的所有單個元素。 – mob 2012-07-13 17:03:27
@mob,他們在技術上不需要*命名*,只是*解除引用*。例如'@ $ ref'和'@ {[qw(foo bar)]}'和'@ a'一樣好。換句話說,它必須以'@'開始(而不是片段)。 – ikegami 2012-07-13 17:46:44
@DVK:我想你可能想要講述當33個參數傳遞時會發生什麼:) – Zaid 2012-07-15 14:43:58