Как вы получаете несколько аргументов в 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
?
Ответы
Ответ 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';