Perlは配列とリストを区別しているが、これが時に罠になる。

 次のスクリプトが、何を表示するか予想できるだろうか。

#!/usr/bin/perl
sub f {
    return ('a','b','c','d');
}
my $count = scalar(f());
warn $count;

関数が配列を返して、その要素数を取っているのだから「4」かな…と思いきや、答えは「d」。なんで?

 まず、関数f配列を返さない。返すのはリストである。括弧にだまされそうになるが、return文における括弧はC同様に意味を持たない。括弧を外しても結果は同じなのは試してみれば分かる。というか、括弧を付けても配列になるわけではなかった。returnを除いても、括弧を二重にしても同じ。配列に代入して初めて配列になる。(追記しました)

 次に、リストをscalar contextで評価すると、要素数ではなく末尾の要素を返す。意図的な挙動なのかは不明だが、スタック構造上そうなるだけかもしれない。

 いずれにしても、リストを返すような実装ははまるので避け、明示的に配列を生成して返した方がいいだろう。あるいはwantarrayを見て、偽ならば次のような値を返すように関数を書けば便利かもしれない。

  • イテレータやハンドル
  • 最初の要素
  • 配列のリファレンス
  • 要素数

 リストをfirst class objectとして扱えないにも関わらず、こんなところで配列との区別を意識しないといけないのは欠陥のようにも思えるが、どうだろう。

 また、contextの罠もはまるとなかなかに痛いので、それはまた別途書くことにする。


Categories : Tech