加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 21:18:36 所属栏目:大数据 来源:网络整理
导读:我正在学习perl,并了解,使用shift打开子例程参数是一个常见且被接受的做法。我也明白,省略函数参数以使用默认的@_数组是常见且可接受的做法。 考虑到这两件事情,如果你调用一个没有参数的子程序,那么@_可以(如果使用shift)就会被改变。这是否意味着使用
我正在学习perl,并了解,使用shift打开子例程参数是一个常见且被接受的做法。我也明白,省略函数参数以使用默认的@_数组是常见且可接受的做法。

考虑到这两件事情,如果你调用一个没有参数的子程序,那么@_可以(如果使用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
}

我的直觉感觉告诉我,使用转换解压缩参数实际上是不好的做法,除非你的子例程实际上应该改变传递的参数,但是我已经在多个地方阅读过,包括Stack Overflow,这不是一个糟糕的做法。

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

解决方法

一般来说,从参数转换是可以的 – 使用& sigil调用函数不是。 (除了在某些非常具体的情况下,你可能永远不会遇到。)

你的代码可以被重写,所以总数不会从@_转移。使用for循环甚至可以更有效率。

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

或者您可以使用List :: Util中的sum函数:

use List::Util qw(sum);

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

使用shift不是常见的,除了在面向对象的Perl中提取$ self。但是,当你总是称之为foo(…)的函数时,如果foo移动或者不移动参数数组,这并不重要。
(值得注意的一个函数的唯一值是它是否分配给@_中的元素,因为它们是您给出的变量的别名作为参数。分配给@_中的元素通常是不好的。)

即使您无法更改总计的实现,也可以使用明确的参数列表调用该子类,因为参数列表是数组的副本:

(a)& total – 呼叫总数与相同的@_,并覆盖原型。
(b)总计(@_) – 电话总数与@_的副本。
(c)& total(@_) – 带有@_的副本,并覆盖原型。

表格(b)是标准的。不应该看到格式(c),除非在同一个包装中的sub的很少的情况下,sub具有原型(并且不使用原型),并且由于某些模糊的原因而必须被覆盖。证明设计不佳。形式(a)仅适用于尾部呼叫(@_ =(…); goto& foo)或其他形式的优化(并且过早优化是所有邪恶的根源)。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读