nDiki

2011年5月23日 (月)

Perl での一時変数のインライン化はコンテキストの変化に注意

Perl ではスカラーコンテキストとリストコンテキストが肝の一つなんだけれど、ここ最近 C++ を使うことが多かったこともありリファクタリングでちょっとポカった。

 #!/usr/bin/perl
 
 use warnings;
 use strict;
 use Data::Dumper;

 sub f { return; }
 sub g { return undef; }

 my $f_value = f;
 my $g_value = g;

 my $f_hash = { a => 1, b => $f_value, c => 3};
 my $g_hash = { a => 1, b => $g_value, c => 3};

 print Dumper($f_hash, $g_hash);

 #$VAR1 = {
 #          'c' => 3,
 #          'a' => 1,
 #          'b' => undef
 #        };
 #$VAR2 = {
 #          'c' => 3,
 #          'a' => 1,
 #          'b' => undef
 #        };

リファクタリング前のコード。$f_hash も $g_hash も同じ。 ここでリファクタリングのスタンダード「一時変数のインライン化」を行う。

 my $f_hash = { a => 1, b => f, c => 3};
 my $g_hash = { a => 1, b => g, c => 3};

 print Dumper($f_hash, $g_hash);

 #Odd number of elements in anonymous hash at test.pl line 13.
 #$VAR1 = {
 #          'a' => 1,
 #          '3' => undef,
 #          'b' => 'c'
 #        };
 #$VAR2 = {
 #          'c' => 3,
 #          'a' => 1,
 #          'b' => undef
 #        };

ああ。f の呼び出しがリストコンテキストに変わるので、 return; が undef ではなく () を返すようになり無名ハッシュを生成するリストの中で消えてしまうため、キーと値の組み合わせがずれてしまう(そして無名ハッシュを奇数個の要素で作ろうとする警告も出る)。

コンテキストは理解しているんだけれど、リファクタリング前のコードでスカラー変数で受けているので、つい f がスカラー値だけを返すサブルーチンだと錯覚してしまうと。

g みたいに明示的に return undef; してればいいかというと、これはこれで落とし穴があり、一般的には return; の方が推奨されている。

Perl での一時変数のインライン化は JavaC++ に比べて要注意ってことで。

スポンサード リンク
[ 5月23日全て ]

About Me

Naney Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。ちょっとしたノートは nNote にあります。

※内容は個人的見解であり所属組織とは関係ありません。

月別インデックス
Process Time: 0.143437s / load averages: 0.25, 0.84, 0.93
nDiki by WATANABE Yoshimasa (Naney)
Powered by DiKicker