В другом вопросе о переполнении стека Леон Тиммерманс утверждал:
Я бы посоветовал вам не использовать прототипы. У них есть свое применение, но не в большинстве случаев и определенно не в этом.
Почему это может быть правдой (или нет)? Я почти всегда поставляю прототипы для своих функций Perl, и я никогда раньше не видел, чтобы кто-то еще говорил что-то плохое об их использовании.
Ответы:
Прототипы неплохие, если их правильно использовать. Сложность состоит в том, что прототипы Perl работают не так, как от них часто ожидают. Люди с опытом работы с другими языками программирования обычно ожидают, что прототипы предоставят механизм для проверки правильности вызовов функций, то есть наличия у них правильного количества и типа аргументов. Прототипы Perl не подходят для этой задачи. Плохо это неправильное использование . Прототипы Perl имеют единственное и совершенно другое назначение:
Прототипы позволяют вам определять функции, которые ведут себя как встроенные функции.
Например, вы можете определить такую функцию:
и назовите это как
без необходимости писать,
\
чтобы получить ссылку на массив.Короче говоря, прототипы позволяют создавать собственный синтаксический сахар. Например, структура Moose использует их для имитации более типичного объектно-ориентированного синтаксиса.
Это очень полезно, но прототипов очень мало:
См. « Прототипы» в perlsub для всех подробностей.
источник
Проблема в том, что прототипы функций Perl не делают того, что люди думают о них. Их цель - позволить вам писать функции, которые будут анализироваться, как встроенные функции Perl.
Во-первых, вызовы методов полностью игнорируют прототипы. Если вы занимаетесь объектно-ориентированным программированием, не имеет значения, какой прототип у ваших методов. (Значит, у них не должно быть прототипа.)
Во-вторых, прототипы строго не соблюдаются. Если вы вызываете подпрограмму с помощью
&function(...)
, прототип игнорируется. Таким образом, они не обеспечивают никакой безопасности типов.В-третьих, они жуткие действия на расстоянии. (Особенно
$
прототип, который заставляет соответствующий параметр оцениваться в скалярном контексте, а не в контексте списка по умолчанию.)В частности, они затрудняют передачу параметров из массивов. Например:
печатает:
вместе с 3 предупреждениями о
main::foo() called too early to check prototype
(если предупреждения включены). Проблема в том, что массив (или срез массива), вычисленный в скалярном контексте, возвращает длину массива.Если вам нужно написать функцию, которая действует как встроенная, используйте прототип. В противном случае не используйте прототипы.
Примечание: Perl 6 будет иметь полностью переработанные и очень полезные прототипы. Этот ответ применим только к Perl 5.
источник
foo()
printts 2, потому что это последний элемент в вашем двухэлементном срезе. Измените на,my @array = qw(foo bar baz)
и вы увидите разницу. (Кстати, вот почему я не инициализирую массивы / списки числовыми последовательностями на основе 0 или 1 в одноразовом демонстрационном коде. Путаница между индексами, счетчиками и элементами в контекстах укусила меня не один раз. Глупо, но факт.)a b c
прояснить вашу точку зрения.Я согласен с двумя вышеупомянутыми плакатами. В общем,
$
следует избегать использования. Прототипы полезны только при использовании блока аргументов (&
), шарики (*
), или ссылки на прототипы (\@
,\$
,\%
,\*
)источник
($)
прототип создает именованный унарный оператор, который может быть полезен (конечно, Perl находит их полезными; я тоже иногда). Во-вторых, при переопределении встроенных модулей (будь то импорт или использование CORE :: GLOBAL: :), вы, как правило, должны придерживаться того прототипа, который был у встроенного модуля, даже если он включает$
, иначе вы можете удивить программиста (вы сами, даже) с контекстом списка, где встроенный в противном случае предоставил бы скалярный контекст.Некоторые люди, глядя на прототип подпрограммы Perl, думают, что это означает то, чего не делает:
Для Perl это означает, что парсер ожидает два аргумента. Это способ Perl, позволяющий создавать подпрограммы, которые ведут себя как встроенные, и все они знают, чего ожидать от следующего кода. О прототипах можно прочитать в perlsub
Не читая документации, люди предполагают, что прототипы относятся к проверке аргументов во время выполнения или чему-то подобному, что они видели на других языках. Как и большинство вещей, которые люди предполагают о Perl, они оказываются неверными.
Однако, начиная с Perl v5.20, в Perl есть экспериментальная функция, на момент написания которой я писал это, которая дает нечто большее, чем то, чего и ожидают пользователи. Сигнатуры подпрограмм Perl выполняют подсчет аргументов во время выполнения, назначение переменных и настройку по умолчанию:
Это функция, которую вы, вероятно, захотите, если вы рассматриваете прототипы.
источник