Проблема полягає в тому, що прототипи функцій Perl не роблять те, що люди думають, що роблять. Їх мета - дозволити записувати функції, які будуть проаналізовані як вбудовані функції Perl.
Перш за все, виклики методів повністю ігнорують прототипи. Якщо ви займаєтесь OO програмуванням, не має значення, яким прототипом є ваші методи. (Тому вони не повинні мати жодного прототипу.)
По-друге, прототипи не застосовуються суворо. Якщо ви викликаєте підпрограму з &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.