Подпись без хлюпанья

Sep 08 2020

Это вопрос о коде, который уже работает! У меня есть много подпрограмм, которые принимают несколько массивов в качестве входных данных, например:

use 5.24.0;
use feature 'refaliasing';
no warnings "experimental::refaliasing";
my (@foo,@bar,@baz);
sub sumarr (\@\@);

# other code to load arrays

sub sumarr (\@\@)
  { my (@sum, @aa, @ab);
    (\@aa,\@ab)=@_;
    $sum[$_] = $aa[$_] + $ab[$_] for 0 .. $#aa;
    return @sum;
    }

... который я могу просто вызвать

@baz = sumarr( @foo, @bar);

Я не нашел способа заменить прототип подписями или хотя бы дополнить прототип подписью для оптимизации списка аргументов. Есть еще что-нибудь, что это делает?

Ответы

2 tobyink Sep 09 2020 at 00:04

Подписи распаковываются @_в лексические переменные, которые ограничены функцией. Прототипы влияют на то, как анализируются вызовы функции . Так что они делают разные вещи - вы не можете просто заменить одно другим. (Вы можете написать функцию, в которой есть и то, и другое.)

Иллюстрация прототипов, влияющих на синтаксический анализ.

use strict;
use warnings;
use Data::Dumper;

my @a = ( 1 );
my @b = ( 2 );

myfunc( @a, @b );

sub myfunc (\@\@) {
    print Dumper( @_ );
}

myfunc( @a, @b );

Обратите внимание, что myfuncдважды вызывается с одними и теми же аргументами, но дает разные результаты. С use warnings, Perl, по крайней мере , предупредить вас , что вы делаете что - то потенциально странное.

Как я уже упоминал, для одной и той же функции можно объявить как подпись, так и прототип.

sub myfunc ( $A, $B ) :prototype(\@\@) {
    print Dumper( @_ );
}

(Сигнатуры все еще экспериментальны, и я считаю, что недавно они изменили порядок объявления подписи и прототипа! Причина остерегаться экспериментальных функций.)

TL; DR: вы не можете заменить прототипы подписями, потому что это разные вещи.