Как получить несколько аргументов в функциях 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";

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

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

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

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

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

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

3 ответов


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

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

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

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

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

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


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

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

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

use List::Util 'sum';

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

или если вам нравится самодокументировать код:

sub addSix {

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

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

конечно, ($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 элемент, остающийся в области sub.
  • если приведены 3 аргумента,@_ пусто, и $y is 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';