【问题标题】:How do you get multiple arguments in Perl functions?如何在 Perl 函数中获取多个参数?
【发布时间】:2012-02-08 12:25:26
【问题描述】:

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

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

【问题讨论】:

  • 注意:避免使用 $a$b 作为变量名,因为它们只能在 sort 块中使用。
  • @Zaid,那是 示例 代码,我实际上命名我的真实变量比那更简洁:-)
  • 显然不是为了添加示例,而是对于需要多个参数的真实子例程,最好开始使用命名参数:my %params = @_; 并将其称为mysub foo => 1, bar => 2, baz => 3, ...
  • @brian d foy 链接似乎已失效。这是同一篇文章吗:effectiveperlprogramming.com/2011/10/…

标签: perl shift


【解决方案1】:

您只需输入:

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

如果您没有该原型,并且如果调用该 sub 时使用了六个以上的参数,则第六个之后的参数只是“不匹配”,$f 将设置为第六个参数。

如果你想捕捉第六个之后的所有参数,你可以这样做。

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

如果您的标量列表比右侧的列表长,则最后一个元素将为undef

【讨论】:

  • 哦。在意外传递十个参数的情况下,$f 是第六个,还是六到十的组合?还是$$$$$$ 会阻止通过十? ...没关系,您的“前四分钟”编辑为我澄清了这一点。
  • 原型阻止传递除六个参数之外的任何东西。如果你没有参数列表原型(所以你可以传递任何东西),$f 仍然是第六个参数,参数列表的其余部分根本不“匹配”。
  • () 周围不需要@_
  • @Zaid:我发现() 位于= 两侧的对称性更美观。
  • 如果你在前面加上&&addSix(1,2)&addSix(1..10),你可以用任意数量的参数调用它。
【解决方案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个参数,@_为空,$yundef 范围。

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

【讨论】:

  • 不是||,而是&&! ;)
猜你喜欢
  • 2014-12-11
  • 1970-01-01
  • 2014-04-18
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 2019-10-11
  • 2022-10-14
相关资源
最近更新 更多