Проблема в том, что прототипы функций 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.