我正在学习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)或其他形式的优化(并且过早优化是所有邪恶的根源)。

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

  1. Swift之旅三函数与闭包

    用func来定义一个函数。试一试去掉day参数。你可以用嵌套函数来把又长又臭的代码组织一下。函数其实是闭包的一个特例。闭包内的代码可以访问到变量和函数必须是与闭包创建的范围是一致的,即便闭包是在另一个范围内执行——在讲嵌套函数时就说过这个例子了。试一试重写这个闭包,对所有奇数都返回0有几种方法可以更简明地写闭包。单行语句的闭包隐式返回语句中的值。作为最后一个参数传到函数里的闭包可以在括号后面马上出现。

  2. Swift 学习笔记 4-函数

    欢迎加QQ群讨论:157672725函数1.使用func来声明一个函数,使用名字和参数来调用函数,使用->来指定函数返回值的类型2.使用元组来让一个函数返回多个值。该元组的元素可以用名称或数字来表示3.函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式4.函数可以嵌套,被嵌套的函数可以访问外侧函数的变量5.函数可以作为另一个函数的返回值6.函数做参数传入另一个函数

  3. Snail—Swift基础学习之函数

  4. Swift学习一:认识必要数据类型

    我很高兴为你讲解我的学习过程。首先,你会问为什么不选择ObjC而是Swift,我想这个问题只有苹果自己知道,我们只有猜。不过从代码结构上来看Swift确实比OC简洁多了,Swift省掉那些OC难以理解的符号,比如NSLog传递消息时是这么写的:NSLog;学过C#的Programmer应该认识这个@,在OC中我不知道怎么理解,所以就不管了。首先,我强烈建议去买台MAC,也就一万左右。我的虚拟机是:VMwareWorkstation12.1.0+OSXEICapitan10.11.2,请原谅我是一个强迫症患

  5. Swift -- 函数的使用(函数作为参数、返回值、嵌套函数)

    {ifarr.count==0{returnnil}varmax:Int=arr[0]varmin:Int=arr[0]varavg:Float=0varsum:Int=arr[0]varindex=0foriteminarr{index++ifitem>max{max=item}ifitemInt{varsum=0;foriteminnums{sum+=item}returnsum}varx=sum()vary=sumvarz=sum//函数嵌套funcfifteen()->Int{varx=10fun

  6. Swift快速入门五集合

    相关文章Swift快速入门(一)第一个Swift程序Swift快速入门(二)基本数据类型Swift快速入门(三)运算符Swift快速入门(四)流程控制前言Swift提供了数组和字典两种集合类型来存储数据,Swift的数组用来存储顺序相同类型相同的类型,字典则采用kay-value的形式存储数据。修改字典字典提供了updataValue()方法来修改字典的value值,该方法会返回一个Sting?

  7. swift 中常用的进制转换

  8. swift-输入输出参数

  9. swift 学习笔记(18)-函数

    函数function有参数有返回值的函数多参函数利用元组实现多返回值可选类型作为参数或者返回值参数标签新特性,默认参数值输入输出参数关键字inout函数类型

  10. 如何在SWIFT中的IOS CORE-DATA请求中使用SQL GROUP BY和SUM函数?

    我有一个表(Transactions),其中包含包含Account_name和交易金额的记录.我想计算每个帐户的所有交易的总额,以“私人”开头,交易金额为>1000.我想按名称按降序排列帐户.所以sql请求会是这样的:我如何在Swift中使用Core-DATA来做到这一点.谢谢请记住,CoreData不是关系数据库,因此您应该认为实体不是“表”,对象不是“记录”.另请注意,按照惯例,属性名称不应以

随机推荐

  1. 数组 – Perl中有什么神奇的数组?

    在Perldocumentationforreverse中,我发现:“请注意,将数组反转到自身(如@a=reverse@a)将尽可能保留不存在的元素;即对于非魔法数组或具有EXISTS和DELETE方法的绑定数组.什么属性区分神奇和非魔法阵列?解决方法一个神奇的阵列是一个执行它的操作不仅仅是改变内容.只有内置的魔术阵列是@ISA,而且这是非常不明显的.正如句子所暗示的,魔术阵列主要是一个绑定的阵列

  2. perl – 使用“isa”方法的最佳方式?

    什么是“最好的”使用方式“isa()”可靠?解决方法Scalar::Util实现明确更好.它避免了eval{}的开销,它总是导致设置一个附加变量.Scalar::Util实现更容易阅读.如果eval也失败了,我相信发生的是你在树之前向后走到eval之前的状态–这是如何实现复位状态.这带来了额外的故障开销.基准根本不是一个对象对象传递isa检查对象出现故障现象检查测试代码:我使用这是为i486-linux-gnu-thread-multi建立的perl,v5.10.1(*),以及Scalar::Util,1

  3. 在CORE :: GLOBAL中哪些Perl内置函数不能被覆盖?

    解决方法toke.c中任何值为负的值都可以被覆盖;所有其他人可能不会.你可以看源码here.例如,我们来看看第10,396行的waitpid:由于waitpid为负数,因此可能会被覆盖.grep怎么样?这是积极的,所以不能被覆盖.这意味着以下关键字不能被覆盖:chop,defined,delete,do,dump,each,else,elsif,eval,exists,for,foreach,format,glob,goto,grep,if,keys,last,local,m,map,my,next,no

  4. 如何在Perl中打印由换行符分隔的列表元素?

    什么是最简单的打印所有列表的元素以Perl中的换行符分隔的元素?解决方法在Perl5.10中:其他方式:或:或者怎么样?

  5. 使用Perl如何获取文件大小(以兆字节为单位)?

    我想以磁盘的形式获取磁盘上的文件大小.使用-s运算符给出了以字节为单位的大小,但是我将假设,然后将其除以魔术数字是一个坏主意:我应该使用只读变量来定义1024,还是有一种编程方式来获取一千字节的字节数?

  6. perl – 如何测试/分类CPAN模块的utf8正确性

    例如:File::Slurp,如果你将读取该文件您将根据命令行开关获得不同的结果,并且perl-CSDA将无法正常工作.伤心.(是的,我知道比Encode::decode(“utf8”,read_file($file,binmode=>’:raw’));将帮助,但是SAD.我的问题:>在这里任何首选方式,如何测试/分类什么CPAN模块是utf8安全/准备/正确?>这里是像Perl::Criticforutf8这样的东西–什么将检查模块源可能的utf8不正确?总结以上是DEVMAX为你收集整理的perl–如

  7. 如何删除Perl字符串中的空格?

    如果我声明一个值为’3’的变量$myString.是否有任何功能来删除返回值的空格.有点像SomeFun然后返回’3′.输出:你可以注意到’vid’=>‘0’,上面的代码从theanswer.我正在研究它.总结以上是DEVMAX为你收集整理的如何删除Perl字符串中的空格?如果觉得DEVMAX网站内容还不错,欢迎将DEVMAX网站推荐给好友。

  8. 如何在mod_perl2下运行Devel :: Cover?

    Unfortunately,Devel::Coverdoesnotyetworkwiththreads.它也不适用于prefork.在startup.pl中使用,Devel::Cover问题perl5.8.9,Apache2.2.13.我的操作系统是FreeBSD,如果重要.同样的问题是reportedforwin32.更新:PerlTrace全部输出解决方法邪恶之源似乎是Apache::DBI.

  9. 如何使用Perl中的C类?

    我有一套用C写的课.从Perl脚本中调用它们的最佳方法是什么?

  10. perl – 在Emacs中以双模式更好的缩进

    我正在使用Emacs来修改Perl和Verilog交织的代码.我正在使用two-mode-mode在两者之间切换,这样可以预期.问题是perl代码与//一行一行地表示;如下图所示:而双模式则认识到它是Perl,它是逐行的,所以缩进等在线上无意义.我想做的是使Perl代码像往常一样格式化,但忽略//;字符.有什么想法吗?我刚刚开始偷看模式文件,它们是可以理解的复杂的,所以任何提示都不会感激!

返回
顶部