Подтвердить что ты не робот

Как вы получаете несколько аргументов в Perl-функциях?

В моем коде я использую довольно примитивный метод извлечения параметров из вызова функции следующим образом:

sub addSix ($$$$$$) {
    my ($a, $b, $c, $d, $e, $f) = (shift, shift, shift, shift, shift, shift);
    return $a + $b + $c + $d + $e + $f;
}

print addSix (1, 2, 3, 4, 5, 6) . "\n";

(забудьте примитивный код, бит выделения - это несколько вызовов shift).

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

my ($a, $b, $c, $d, $e, $f) = shift (6);

или что-то подобное.

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

Как вы можете извлекать параметры, не вдаваясь в брань с ключевыми словами shift?

4b9b3361

Ответ 1

Вы можете просто ввести:

my ($a, $b, $c, $d, $e, $f) = (@_);

Если у вас не было этого прототипа, и если этот sub получил вызов с более чем шестью аргументами, то после шестого просто "не совпадают", $f будет установлен на шестой аргумент.

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

my ($a, $b, $c, $d, $e, $f, @others) = (@_);

Если ваш список скаляров длиннее списка с правой стороны, последние элементы будут undef.

Ответ 2

Использование прототипов сильно обескуражено, если для этого не существует реальной потребности.

Как всегда с Perl, существует несколько способов сделать это.

Здесь один из способов гарантировать добавление только первых шести параметров, которые передаются:

use List::Util 'sum';

sub addSix { sum @_[0..5] }

Или, если вам нравится самодокументирующий код:

sub addSix {

    my @firstSix = @_[0..5];  # Copy first six elements of @_
    return sum @firstSix;
}

Ответ 3

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

Конечно, ($x, $y) = @_ отлично, если вы хотите сохранить @_, но, возможно, вы хотите поменять свои аргументы по какой-то причине? Возможно, вам нужна любая дополнительная функция подпрограммы, определяемая количеством оставшихся аргументов в @_.

Самый чистый однострочный путь, который я мог бы придумать, - это простая карта

sub shiftySub {
    map { $_ = shift } my ($v, $w, $x, $y);
    # @_ now has up to 4 items removed
    if (@_) { ... } # do stuff if arguments remain
}
  • Если указано 4 аргумента, @_ теперь пуст в подпункте.
  • Если указано 5 аргументов, @_ имеет 1 элемент, оставшийся в подпункте.
  • Если указаны 3 аргумента, @_ пуст, а $y - undef в подпункте сфера.

Что касается paxdiablo теоретического оператора shift(6), мы могли бы создать свою собственную функцию, которая выполняет эту операцию...

sub shifter (\@;$) {
    my ( $array, $n ) = ( @_, 1 );
    splice( @$array, 0, $n );
}

Функция работает, применяя прототип pass-by-ref (одна из очень ограниченных причин, по которой вы должны использовать прототипы), чтобы гарантировать, что массив смещается в области вызова. Затем вы используете его просто так...

my @items = ('one', 'two', 'three', 'four');
my ($x, $y) = shifter(@items, 2);
# or as a replacement for shift
my $z = shifter(@items)
# @items has 1 item remaining in this scope!

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

Надеюсь, что my $post = 'informative' || 'interesting';