Вопрос

В еще один вопрос о переполнении стека Леон Тиммерманс утверждал:

Я бы посоветовал вам не использовать прототипы.У них есть свое применение, но не в большинстве случаев и уж точно не в этом.

Почему это может быть правдой (или иначе)?Я почти всегда предоставляю прототипы своих функций Perl и никогда раньше не видел, чтобы кто-нибудь говорил что-то плохое об их использовании.

Это было полезно?

Решение

Прототипы неплохие, если их правильно использовать.Трудность в том, что прототипы Perl работают не так, как от них часто ожидают люди.Люди, имеющие опыт работы с другими языками программирования, склонны ожидать, что прототипы предоставят механизм проверки правильности вызовов функций:то есть, что у них есть правильное количество и тип аргументов.Прототипы Perl не очень подходят для этой задачи.Это злоупотребление плохо.Прототипы Perl имеют единственную и совершенно разную цель:

Прототипы позволяют определять функции, которые ведут себя как встроенные функции.

  • Круглые скобки необязательны.
  • Контекст накладывается на аргументы.

Например, вы можете определить такую ​​функцию:

sub mypush(\@@) { ... }

и назовите это как

mypush @array, 1, 2, 3;

без необходимости писать \ чтобы получить ссылку на массив.

Короче говоря, прототипы позволяют вам создавать свой собственный синтаксический сахар.Например, платформа Moose использует их для эмуляции более типичного объектно-ориентированного синтаксиса.

Это очень полезно, но прототипы очень ограничены:

  • Они должны быть видимы во время компиляции.
  • Их можно обойти.
  • Распространение контекста на аргументы может привести к неожиданному поведению.
  • Они могут затруднить вызов функций, используя что -либо, кроме строго предписанной формы.

Видеть Прототипы в perlsub для всех кровавых подробностей.

Другие советы

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

Я согласен с вышеуказанными двумя постерами. В общем, следует избегать использования $ . Прототипы полезны только при использовании аргументов блока ( & amp; ), глобусов ( * ) или ссылочных прототипов ( \ @ , \ $ , \% , \ * )

Некоторые люди, глядя на прототип подпрограммы Perl, думают, что это означает то, чего нет:

sub some_sub ($) { ... }

Для Perl это означает, что синтаксический анализатор ожидает два аргумента. Это способ Perl позволять вам создавать подпрограммы, которые ведут себя как встроенные модули, и все они знают, чего ожидать от следующего кода. Вы можете прочитать о прототипах в perlsub

Не читая документацию, люди предполагают, что прототипы ссылаются на проверку аргументов во время выполнения или что-то подобное, что они видели в других языках. Как и большинство вещей, которые люди предполагают о Perl, они оказываются неправы.

Однако, начиная с Perl v5.20, у Perl есть особенность, экспериментальная, когда я пишу это, которая дает нечто большее, чем то, что пользователи ожидают и что. подписи подпрограмм Perl выполняет подсчет аргументов во время выполнения, переменная назначение и настройка по умолчанию:

use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);

animals( 'Buster', 'Nikki', 'Godzilla' );

sub animals ($cat, $dog, $lizard = 'Default reptile') { 
    say "The cat is $cat";
    say "The dog is $dog";
    say "The lizard is $lizard";
    }

Эта функция, вероятно, вам нужна, если вы рассматриваете прототипы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top