$#arrayを事前にインクリメントするとはどういう意味ですか?
質問
次のコード行に出会いました。問題があります:
- プッシュと同じことを行うことを意図しています
- プッシュを使用する必要があります
- 読みにくく、理解しにくい
- プッシュを使用するように変更しました
- 違法だと思ったことがありますが、明らかに違法ではありません
ここにあります:
$array [++$#array] = 'data';
私の質問は、$#arrayを事前にインクリメントすることはどういう意味ですか?私は常に$#arrayは配列の属性であり、書き込み可能ではないと考えていました。
解決
perldata のコメント:
"配列の長さはスカラー値です。 cshのように$#daysを評価することで、配列@daysの長さを見つけることができます。ただし、これは配列の長さではありません。これは最後の要素の添え字です。通常は0番目の要素があるため、異なる値になります。 $#daysに割り当てると、実際には配列の長さが変わります。この方法で配列を短くすると、介在する値が破壊されます。以前に短縮された配列を延長しても、それらの要素にあった値は復元されません。"
場合によっては$#arrayを変更すると便利ですが、この場合は明らかにpushの方が優れています。
他のヒント
ポストインクリメントは、最初に変数を返し、次に変数をインクリメントします。
ポストインクリメントを使用した場合、最後に返された要素を変更し、最後に空の要素をプッシュします。 2番目のループでは、その空の値を変更し、後で空の値をプッシュします。したがって、プッシュのようにはまったく機能しません。
プリインクリメントは変数をインクリメントしてから返します。そうすれば、例は常に配列の新しい最後の要素に書き込みを行い、プッシュのように動作します。以下の例:
my (@pre, @post);
$pre[$#pre++] = '1';
$pre[$#pre++] = '2';
$pre[$#pre++] = '3';
$post[++$#post] = '1';
$post[++$#post] = '2';
$post[++$#post] = '3';
print "pre keys: ".@pre."\n";
print "pre: @pre\n";
print "post keys: ".@post."\n";
print "post: @post\n";
出力:
pre keys: 3
pre: 2 3
post keys: 3
post: 1 2 3
現在の配列の長さより大きい値を $#array
に割り当てると、配列が拡張されます。
このコードも機能します:
$ perl -le 'my @a; $a[@a]="Hello"; $a[@a]=" world!"; print @a'
Hello world!
Perl配列は動的で、制限を超えて割り当てると大きくなります。
まず第一に、それはファウルです。
とはいえ、それが機能することにも驚いています。 ++ $#array
が「定数を変更できません」を取得したと推測していました。数値をインクリメントしようとするとエラーが発生します。 (もちろん、私が誤ってそうすることはありません。)しかし、私たちが間違っていたのはまさにそれだと思います。 $#array
は定数(数値)ではありません。それは変数式です。そのため、それを台無しにすることができます。以下を考慮してください。
my @array = qw/1 2 3/;
++$#array;
$array[$#array] = qw/4/;
print "@array\n"
さらに、さらに楽しくするために、これ:
my @array = qw/1 2 3/;
$#array += 5;
foreach my $wtf (@array) {
if (defined $wtf) {
print "$wtf\n";
}
else {
print "undef\n";
}
}
そして、ええ、 Perl Cookbook は $#array
をいじって配列を拡大または切り捨てます(第4章、レシピ3)。私はまだいですが、多分それは長引く「しかし、それは数字です」偏見。