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

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

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 ключевых слов?

Ответы [ 3 ]

32 голосов
/ 12 января 2012

Вы можете просто набрать:

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

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

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

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

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

7 голосов
/ 12 января 2012

Использование прототипов настоятельно не рекомендуется, если в этом нет необходимости real .

Как всегда с 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 голосов
/ 08 мая 2015

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

Конечно, ($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 );
}

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

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';

...