無駄と文化

実用的ブログ

return; で何が返されるか【Perl ネタ】

Perl ネタです。

 

sub f { return; }

sub g { return undef; }

上記の fg は違うという話をします。

 

違いのわかるコード

sub f { return; }

print Dumper f;
# => ''

print Dumper { map { $_ => f } (1..4) };
# => '{ 1 => 2, 3 => 4 }'

sub g { return undef; }

print Dumper g;
# => 'undef'

print Dumper { map { $_ => g } (1..4) };
# => '{ 1 => undef, 2 => undef, 3 => undef, 4 => undef }'

return; しているサブルーチンを使って構成されている HashRef はなんだか思わぬ形をしていますね。

 

違いがわかりやすいコード

もっとわかりやすい例を、

sub f { return; }

print Dumper [ map { f } (1..4) ];
# => '[]'

sub g { return undef; }

print Dumper [ map { g } (1..4) ];
# => '[undef, undef, undef, undef]'

この例で云うと、 return; からは空リスト () が返されているようです。
return undef; から返されているのはもちろん undef です。

 

return; から返される値はコンテキストに依る

return; から返される値はコンテキストに依ります。
Perldoc にはこう書かれています。

return EXPR
(中略)
EXPR の評価は、返り値がどのように使われるかによってリスト、スカラ、 無効コンテキストになります;
EXPR が指定されなかった場合は、リストコンテキストでは空リストを、スカラコンテキストでは未定義値を返します;
そして (もちろん) 無効コンテキストでは何も返しません。

Perlの組み込み関数 return の翻訳 - perldoc.jp より

なるほど。
return; されて返った先がリストコンテキストだったら空リスト () が返されると明記されていますね。

一方で return undef; で返った先がリストコンテキストだった場合は、undef がリストコンテキストで評価されて (undef) として扱われることになります。

 

return; しているサブルーチンをハッシュの値に置きたいときはどうするか

仕組みは分かったものの、
内部で return; しているサブルーチンをハッシュの値に置いたとき下記のようになるのはやはり狙った挙動ではないでしょう。

sub f { return; }

print Dumper { map { $_ => f } (1..4) };
# => '{ 1 => 2, 3 => 4 }'

これを回避するためには、f が評価されるときにスカラコンテキストを強制してあげればいいですね。
具体的には scalar を使ってあげて。

sub f { return; }

print Dumper { map { $_ => scalar f } (1..4) };
# => '{ 1 => undef, 2 => undef, 3 => undef, 4 => undef }'

これで狙った挙動になりましたね。

 

まとめ

return;return undef; にも細かなところで違いがあるんですね。

"コンテキスト" は人類には早すぎる。

 

 

私からは以上です。