如何在Perl函数中获得多个参数?

如何在Perl函数中获得多个参数?,perl,shift,Perl,Shift,在我的代码中,我一直在使用相当原始的方法从函数调用中提取参数,如下所示: 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调用) 现在,这对我

在我的代码中,我一直在使用相当原始的方法从函数调用中提取参数,如下所示:

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
关键字?

您只需键入:

my ($a, $b, $c, $d, $e, $f) = (@_);
如果您没有该原型,并且如果使用六个以上的参数调用该sub,则第六个参数后面的参数只是“不匹配”,那么,
$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项
  • 如果提供了3个参数,
    @
    为空,
    $y
    在子字段中为
    undef
    范围

关于的理论
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!
当然,您也可以在其他潜艇内使用此
移位器
功能。这样的函数的主要缺点是必须跟踪运算符两侧的赋值数量


我希望
my$post='informational'| | |有趣'

D'Oh。在意外传递十个参数的情况下,
$f
是第六个参数,还是六到十个参数的组合?还是
$$$$$$
会阻止通过十个。。。没关系,你的“在前四分钟”编辑为我澄清了这一点。原型阻止传递除六个参数以外的任何参数。如果您没有参数列表原型(因此您可以传递任何东西),
$f
仍然是第六个参数,参数列表的其余部分根本不“匹配”。没有必要在
@
@周围使用
()
:我发现拥有
()
=
的两侧更美观。如果您在它前面加上
&
&addSix(1,2)
&addSix(1..10),则可以使用任意数量的参数调用它
。注意:避免使用
$a
$b
作为变量名,因为它们仅用于
排序
块中。@Zaid,这是示例代码,我实际上对真实变量的命名比这要简洁一些:-)显然不是用于add示例,但是对于一个实际的子例程,如果它需要超过几个参数,那么最好开始使用命名参数:
my%params=@并将其称为
mysub foo=>1,bar=>2,baz=>3,
@brian d foy link似乎死了。这是同一篇文章吗:?为什么不鼓励原型?我原以为它们在检测需要固定数量的参数的情况下是非常宝贵的。@paxdiablo:我会让你参考。还有。@paxdiablo:有趣的是,我得去看看。然而,就像“代码完成”一样,很多信息技术都需要作为指导原则——例如,请参见Randal L Schwartz本人的评论:-)不是|,而是事实上&&!)