プロトタイプの部分はカバーしません (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;
}
このメソッドで珍しいことの 1 つは、function signature (prototype)
.
sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@) {
@mob と @ikegami がコメントで賢明に指摘したように、
... Perl に 2 ~ 32 個の名前付き配列を想定し、それらを配列参照として (@_ で) 関数に渡すように指示します。したがって、 を呼び出すmesh @a,@b,@c
と、@_
in mesh は、 ( mob )(\@a,\@b,\@c)
のすべての個々の要素を含む 1 つの「フラット」リストではなく設定され
ます ... 技術的には、名前を付ける必要はなく、逆参照するだけです。たとえば、 と同様に機能します。言い換えれば、それは(スライスではなく)で始まる必要があります。(池上)@a, @b, and @c
@$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);
これは、個々の配列 (arrayref ではなく) を、組み込みのように動作する関数 (例: map
/ sort
)に引数として渡すことができるようにするためです。
を呼び出すパラメーターとして 1 つまたは 33 個の配列がリストされている場合に何が起こるかについての Zaid のクエリに答えるに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.