В perl, что означает заключенный в скобки список '$' в вложенном объявлении? - PullRequest
3 голосов
/ 15 октября 2019

Я должен отладить чужой код и наткнулся на подчиненные объявления, которые выглядят следующим образом ...

sub mysub($$$$) {
    <code here>
}

... также ...

sub mysub($$$;$) {
    <code here>
}

Что означаетзаключенный в скобки список '$' (с необязательным ';') означает? Я провел эксперимент, и мне все равно, если я передам подпрограмме, объявленной таким образом, все больше и меньше аргументов, чем в списке «$». Я думал, что это может быть использовано для устранения неоднозначности двух разных подпрограмм с одинаковым именем, отличающихся только количеством аргументов, переданных ему (как определено в ($$$$) vs ($$$) vs ($$)и т.д... ). Но, похоже, это не так.

Ответы [ 2 ]

7 голосов
/ 15 октября 2019

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

Элементы после ; являются необязательными аргументами. Итак, mysub($$$$) имеет четыре обязательных аргумента, а mysub($$$;$) имеет три обязательных аргумента и один необязательный аргумент.

Немного о разборе

Perl позволяет вам немного разбираться в скобках, когда выхочу указать аргументы, поэтому они одинаковы:

print "Hello World";
print( "Hello World\n" );

Это один из философских моментов Perl. Когда мы можем опустить шаблон, мы должны быть в состоянии.

Кроме того, Perl позволяет передавать подпрограмме столько аргументов, сколько вам нужно, и вам не нужно заранее ничего говорить о параметрах:

sub some_sub { ... }
some_sub( 1, 2, 3, 4 );
some_sub 1, 2, 3, 4;   # same

Это еще одна основополагающая идеяPerl: у нас есть скаляры и списки. Многие вещи работают в списке, и нам все равно, что в нем или сколько у него элементов.

Но некоторые встроенные функции принимают определенное количество аргументов. sin принимает ровно один аргумент (но print переводит ноль в бесконечность):

print sin 5, 'a'; # -0.958924274663138a  (a is from `a`)

rand принимает ноль или один:

print rand;    # 0.331390818188996
print rand 10; # 4.23956650382937

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

Я склонен использовать парены в списках аргументов, потому что я считаю, что это прощечтобы люди увидели, что я намерен (хотя не всегда с print, я думаю):

print sin(5), 'a';

Есть одно интересное использование прототипов, которое мне нравится. Вы можете создать свой собственный синтаксис, который работает как блочные формы map и grep:

map { ... } @array;

Если вы хотите поэкспериментировать с этим (но все еще не подчиняющимся программистам обслуживания), ознакомьтесь с Object :: Iterate для демонстрации этого.

Экспериментальные подписи

В Perl v5.20 появилась экспериментальная функция подписи , где вы можете давать именапараметры. Все это необходимо:

use v5.20;
use feature qw(signatures);
sub mysub ( $name, $address, $phone ) { ... }

Если вам нужен необязательный параметр, вы можете задать ему значение по умолчанию:

sub mysub ( $name, $address, $phone = undef ) { ... }

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

no warnings qw(experimental::signatures);
0 голосов
/ 16 октября 2019

Это интересно.

Я провел эксперимент, и мне все равно, если я передам больше и меньше аргументов подпрограмме, объявленной таким образом, чем в списке '$'.

Потому что, конечно, это именно то, что автор кода пытался применить.

Существует два способа обойти подсчет параметров, которые должны обеспечивать прототипы.

  1. Вызов подпрограммы как метода для объекта ($my_obj->my_sub(...)) или для класса (MyClass->my_sub(...)).
  2. Вызов подпрограммы с использованием синтаксиса «старого стиля» амперсанда (&my_sub(...)).

Из чего мы учимся:

  1. Не используйте прототипы в подпрограммах, которые предназначены для использования в качестве методов.
  2. Не используйте синтаксис амперсанда для вызова подпрограмм.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...