ちょっと前に作ったプログラムを見ていて、悪い習慣だなぁ、と思ったので、改めるためにメモ。
Perlを覚えていく中で、関数の返り値を偽として判定させたいときは「undefを返す」という事をやっていた。

1
return undef;

しかし、これは返り値を配列で受け取るときに微妙になり、わかりにくいバグを発生させてしまう原因にもなる。
どういう場合に問題になるかを、実際にコードを書いて試してみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# utf8
use 5.8.1;
use strict;
use warnings;
use utf8;
use Perl6::Say;
use Data::Dumper qw/Dumper/;
my $charset = 'cp932';
binmode STDOUT => ":encoding($charset)";
sub return_less {
my $a = 1;
}
sub return_undef {
my $a = 1;
return undef;
}
sub return_only {
my $a = 1;
return;
}
# return_less
if (my @result = &return_less) {
say 'return_less : true';
print Dumper \@result;
}
else {
say 'return_less : false';
print Dumper \@result;
}
# return_undef
if (my @result = &return_undef) {
say 'return_undef : true';
print Dumper \@result;
}
else {
say 'return_undef : false';
print Dumper \@result;
}
# return_only
if (my @result = &return_only) {
say 'return_only : true';
print Dumper \@result;
}
else {
say 'return_only : false';
print Dumper \@result;
}

このスクリプトを実行すると結果はそれぞれどうなるでしょうか?
しばらく考えてみて下さい。


答えは以下のようになります。

1
2
3
4
5
6
7
8
9
10
return_less  : true
$VAR1 = [
1
];
return_undef : true
$VAR1 = [
undef
];
return_only : false
$VAR1 = [];

いかがでしょうか?
undefを返したのに、分岐で「真」になっていますね。
これは、if文が@resultを要素数で判定したためです。
undefを返すと、見ての通り@resultに「undef」が代入されます。
そのため、@resultの判定が1となり、真となります。
期待したのは「return_only」のような動作ではないでしょうか?
return undef;は悪癖です。
理解してやる場合は別ですが、殆どの場合は単独のreturnが良いでしょう。