gpt4 book ai didi

perl - 在 perl 中,使用默认参数调用多个子例程是不好的做法吗?

转载 作者:行者123 更新时间:2023-12-03 13:56:23 25 4
gpt4 key购买 nike

我正在学习 perl,并了解使用 shift 解包子例程参数是一种常见且公认的做法。我也明白,省略函数参数以使用默认值 @_ 是常见且可接受的做法。大批。

考虑到这两件事,如果你调用一个不带参数的子程序,@_可以(并且将会,如果使用类次)被改变。这是否意味着使用默认参数调用另一个子程序,或者实际上使用 @_在此之后的数组,是否被认为是不好的做法?考虑这个例子:

sub total { # calculate sum of all arguments
my $running_sum;
# take arguments one by one and sum them together
while (@_) {
$running_sum += shift;
}
$running_sum;
}

sub avg { calculate the mean of given arguments
if (@_ == 0) { return }
my $sum = &total; # gets the correct answer, but changes @_
$sum / @_ # causes division by zero, since @_ is now empty
}

我的直觉告诉我,使用 shift 来解包参数实际上是不好的做法,除非您的子例程实际上应该更改传递的参数,但我在多个地方读到过,包括 Stack Overflow,这不是一个不好的做法。

所以问题是:如果使用 shift 是常见的做法,我是否应该总是假设传递的参数列表可能会被更改,作为子例程的副作用(如引用示例中的 &total 子例程)?有没有办法按值传递参数,所以我可以确定参数列表不会改变,所以我可以再次使用它(如引用文本中的 &avg 子例程)?

最佳答案

一般情况下,shift从参数中提取是可以的——使用 &调用函数的符号不是。 (除了一些你可能永远不会遇到的非常特殊的情况。)

您的代码可以重写,以便 totalshift来自 @_ .使用 for 循环甚至可能更有效。

sub total {
my $total = 0;
$total += $_ for @_;
$total;
}

或者您可以使用 sum函数来自 List::Util :
use List::Util qw(sum);

sub avg { @_ ? sum(@_) / @_ : 0 }

使用 shift不是很常见,除了提取 $self在面向对象的 Perl 中。但正如你总是调用你的函数,如 foo( ... ) , foo 没关系 shift是或不是 shift参数数组。
(关于函数唯一值得注意的是它是否分配给 @_ 中的元素,因为这些是您作为参数提供的变量的别名。分配给 @_ 中的元素通常是不好的。)

即使你不能改变 total 的实现,使用显式参数列表调用 sub 是安全的,因为参数列表是数组的副本:

(一) &total — 调用 total具有相同的 @_ , 并覆盖原型(prototype)。
(b) total(@_) — 调用 total带有 @_ 的副本.
(c) &total(@_) — 调用 total带有 @_ 的副本, 并覆盖原型(prototype)。

表格 (b) 是标准的。表格 (c) 不应该被看到,除非在极少数情况下,在同一个包中的 subs 有一个原型(prototype)(并且不使用原型(prototype)),并且由于一些模糊的原因它们必须被覆盖。糟糕设计的证明。
形式 (a) 仅适用于尾调用 ( @_ = (...); goto &foo ) 或其他形式的优化(过早优化是万恶之源)。

关于perl - 在 perl 中,使用默认参数调用多个子例程是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14100589/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com