Perl 戻り値を返さない関数の戻り値をそのまま配列に入れると消える

$ perl -v
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi

予想してなかったところで、 Odd number of elements in hash assignment の警告が出ていたので、いろいろ調べていたら、Perlの動作でちょっと驚いたことがあったので記録しておきます。

use strict;
use warnings;
use Smart::Comments;
 
sub no_value {}
 
sub undef_value { return undef; }
 
my @arr;
 
### undefを返す関数の戻り値を直接配列に代入する
@arr = (1, 2, undef_value, 3);
### @arr;
 
### 値を返さない関数の戻り値を直接配列に代入する
@arr = (1, 2, no_value, 3);
### @arr;
 
### 値を返さない関数の戻り値を一度変数に代入後、配列に代入する
my $no_value = no_value;
@arr = (1, 2, $no_value, 3);
### @arr;

予想してたのは、全部の場合で、@arrの中身は[1, 2, undef, 3]になると思っていたところ、

### undefを返す関数の戻り値を直接配列に代入する
 
### @arr: [
###         1,
###         2,
###         undef,
###         3
###       ]
 
### 値を返さない関数の戻り値を直接配列に代入する
 
### @arr: [
###         1,
###         2,
###         3
###       ]
 
### 値を返さない関数の戻り値を一度変数に代入後、配列に代入する
 
### @arr: [
###         1,
###         2,
###         undef,
###         3
###       ]

関数の戻り値を使うときに、そのまま配列の要素として使った場合(2番目の例)、3番目の要素が無視されて、@arrの要素が3つになってしまった。 一度スカラー変数 $no_valueに代入した結果を使った場合(3番目の例)、結果は予想通り@arrの要素が4つになった。

配列の要素として使用した時に、リストコンテキストとして評価されて、要素0の配列として扱われてしまい、 一度スカラー変数に代入した時には、強制的にスカラーコンテキストとして評価されるのでundefになってくれる。 ということだろうか。それなら説明はつく。

3 Comments

  • return () と return undef の違い

  • perl はreturn がない関数では return wantarray () : undef; みたいなことをするはず。 配列のなかやハッシュのなかではコンテキストはリストなので、 まさにおっしゃるとおりでしょう。

  • kenihi さん

    return wantarray () : undef;

    納得です。ありがとうございます。

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.