8

配列に値が出現する回数を数える簡単なPerlを次に示します。これは警告なしで実行されます。

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{$_}++;
}

ループ本体をに変更した場合

$histogram{$_} = $histogram{$_} + 1;

Perlは、「初期化されていない値を追加で使用する」と警告します。

内部で何が起こっているのですか?++演算子にオペランドとして提供され、+演算子で初期化されていない場合、値が初期化されるのはなぜですか?

4

4 に答える 4

15

+ 演算子は、左側のフォームと右側のフォームの両方を評価し、両方の合計を返します。ハッシュ呼び出しの評価では、特別なコンテキストは見られません。

++ 演算子には、いくつかの特別な魔法が組み込まれています。++ 演算子に関する perlop manpage からの引用:

「undef」は常に数値として扱われ、特にインクリメントする前に 0 に変更されます (そのため、undef 値のポストインクリメントは「undef」ではなく 0 を返します)。

edit : 違いを詳しく説明すると、 ++ はその場で値を変更しますが、 + はその引数を入力として受け取るだけです。+ に未定義の値が表示される場合、通常は何かが間違っていますが、++ の場合、ハッシュ操作の例は非常に典型的です。ユーザーは、毎回チェックして初期化するのではなく、undef を 0 として扱いたいと考えています。したがって、これらの演算子をこのように扱うのは理にかなっているようです。

于 2008-11-04T03:05:05.047 に答える
8

特定の演算子は、左側または唯一のオペランドのデフォルト値 0 または "" が意味をなす状況で一般的に使用されるため、利便性のために「初期化されていない」警告を意図的に省略しています。

++ および -- (前または後)、+=、-=、.=、|=、^=、&&=、||= です。

これらのいくつかは、tie 変数で使用すると誤って警告を出すことに注意してください: http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.tで TODO とマークされたテストを参照してください。 .

于 2008-11-04T04:52:55.170 に答える
8

Perl が必ずしも値を初期化するわけではありませんが、常に警告するわけではありません。常に例外を見つけるので、これに関するルールを考えようとしないでください。そして、それを理解したと思ったときに、Perl の次のバージョンで警告が変更されます。

この場合、ハーレクインが言ったように、自動インクリメント演算子には特殊なケースがあります。

于 2008-11-04T03:22:02.390 に答える
0

ブライアンが言ったように、それはまだそれを行います、それはあなたに警告するだけです. 警告は、意図していない可能性のある影響を伴う特定の操作について通知します。

具体的には の値を要求$histogram{$_}し、それに 1 を追加してから、同じスロットに割り当てます。ここで自動有効化が機能するとは思わないのと同じです。

my $hash_ref = $hash_for{$key_level_1};
$hash_ref->{$key_level_2} = $value;

ここで行うように:

$hash_for{$key_level_1}{$key_level_2} = $value;

魔法はおそらく最適化のようには機能しません。a = a + 1そして、最適化コンパイラは、アセンブリ言語にインクリメント演算子があった場合と同じことに気付くでしょうa++。最初の値を保持する必要があると偽って、そうでないために上書きする代わりに、その最適化された命令を使用できます。実際に必要です。

最適化は、実行ごとにパフォーマンスを改善するための余分な精査とオーバーヘッドです。しかし、動的言語では、他の方法で削減しようとするのと同じ速度でオーバーヘッドを追加していないという保証はありません。

于 2008-11-04T04:14:25.577 に答える