Perlでは、任意の関数が呼び出される文脈をスカラ、リスト、またはvoidに定義できます。演算子wantarrayは、コンテキストを判断するために使用されます。
例:
sub foo { if (wantarray) { return (1, 2, 3); # リストとして } else { return 42; # スカラとして } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # voidコンテキスト
特徴: wantarrayを正しく使用しないと、予期しない値を返す事があります。
関数がコンテキストに応じて配列とスカラを返し、voidコンテキストで呼び出された場合、何が返されるでしょうか?
回答: voidコンテキストでは、返された値は無視されますが、wantarrayによる分岐のコード自体は存在します。したがって、関数が副作用を持つ場合は、別の処理を考慮する必要があります。例えば:
sub noisy { if (wantarray) { print "リストコンテキストで呼ばれました"; return (1,2,3); } elsif (defined wantarray) { print "スカラとして呼ばれました"; return 42; } else { print "Void!"; return; } }
物語 1
プロジェクトでは、あるエンジニアがコンテキストの違いを忘れていました。ファイル名のリストを返す関数が、時々ファイル数(スカラコンテキスト)だけを返すことがあり、他の結果との連結でデータ損失が発生しました。
物語 2
ヘッダーを解析するためのAPIを開発しているとき、関数は明示的に左側に配列がある場合にのみリストを返しました(
my @headers = parse_headers())、if (parse_headers())のように呼び出すと、最初のヘッダーのみが返されました。このバグはすぐには見つかりませんでしたが、処理は論理的に見えましたが、プロジェクトの異なる部分で動作が異なっていました。
物語 3
ファイル内の一致を検索する関数がコンテキストによって異なる数の結果を返していました。その結果、mapやgrepに渡すと予期しないエラーが発生しました: mapはリストを期待していましたが、undefを受け取り、スカラコンテキストでは見つかった一致の数のみが考慮されました。この問題は数回のリリース後にしか発見されませんでした。