Проблема в том, что прототипы функций Perl не делают то, что думают люди. Их цель - дать вам возможность писать функции, которые будут анализироваться, как встроенные функции Perl.
Прежде всего, вызовы методов полностью игнорируют прототипы. Если вы занимаетесь ОО-программированием, не имеет значения, какой прототип есть у ваших методов. (Таким образом, у них не должно быть никакого прототипа.)
Во-вторых, прототипы не строго соблюдаются. Если вы вызываете подпрограмму с &function(...)
, прототип игнорируется. Таким образом, они действительно не обеспечивают никакой безопасности типа.
В-третьих, они пугающие действия на расстоянии. (Особенно прототип $
, который вызывает оценку соответствующего параметра в скалярном контексте вместо контекста списка по умолчанию.)
В частности, они затрудняют передачу параметров из массивов. Например:
my @array = qw(a b c);
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
sub foo ($;$$) { print "@_\n" }
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
печать:
a b c
a b
a b c
3
b
a b c
вместе с 3 предупреждениями о main::foo() called too early to check prototype
(если предупреждения включены). Проблема в том, что массив (или срез массива), вычисленный в скалярном контексте, возвращает длину массива.
Если вам нужно написать функцию, которая действует как встроенная, используйте прототип. В противном случае не используйте прототипы.
Примечание: Perl 6 будет иметь полностью обновленные и очень полезные прототипы. Этот ответ относится только к Perl 5.