У программиста в проекте встречался примерно такой код:
sub g
{
my ($n) = @_;
if ( $n > 30 || $n <= 0 ){
return;
} elsif ( $n == 1 ){
return [1];
}
my @arr = (1,1);
for my $i (2 .. $n-1){
$arr[$i] = $arr[$i-1] + $arr[$i-2];
}
return \@arr;
}
sub f
{
my ($arr, $x) = @_;
if (!$arr){
return '';
}
for my $i (0 .. @$arr - 1){
if ($arr->[$i] == $x){
return $i;
}
}
return '';
}
Но вот беда: при некоторых сочетаниях параметров код некорректно завершается.
Например, f(g(25),144)
работает нормально, а f(g(50),1134903170)
– падает.
Для отладки программист добавил отладочную печать промежуточных значений:
$z = g(50);
print STDERR "g(50): $z\n";
f($z, 1134903170);
Удивительно, но с отладочной печатью все сработало правильно!
Впрочем, появился ворнинг:
Use of uninitialized value $z in concatenation (.) or string
Функция g
выполняется в списковом контексте,
а в списковом контексте return
без параметра возвращает пустой список,
и при интерполяции всех параметров для f
получается список из одного элемента: (1134903170)
.
Таким образом, первоначальный вызов f(g(50),1134903170)
равнозначен f(1134903170)
,
то есть порядок аргументов f
портится.
С отладочной же печатью получается f(undef, 1134903170)
.
Мораль: если функция используется ради возвращаемого значения (не ради побочных эффектов)
– лучше избегать в ней оператора return
без параметра.