• Perl学习笔记04——子程序


    ▲说明

    1.子程序的名字只能以字母、数字和下划线组成,同时不能以数字开头。

    2.调用子程序可在其名字前加上与号(&),表示调用动作。

    3.子程序名属于独立的名字空间,Perl不会把&fred$fred搞混,因为它们分属于不同的命名空间。

    定义子程序

    定义子程序的方法

    先用关键字sub开头,再写上子程序名,然后写上花括号,封闭在花括号里的代码块就是子程序的主体。

    sub marine{
        $n += 1;  #全局变量$n
        print "Hello, sailor number $n!
    "; 
    }

     NOTE

    1.子程序可以被定义在程序中的任意位置,放在文件的开头、结尾都可以。

    2.子程序的定义是全局的。

    3.加入定义了两个重名的子程序,后面的子程序会覆盖前面的。

    4.可以在子程序中使用任何全局变量。

    调用子程序

    子程序名前加上与号(&)就表示调用这个子程序,也叫呼叫子程序。

    &marine;  #打印 Hello, sailor number 1!
    &marine;  #打印 Hello, sailor number 2!
    &marine;  #打印 Hello, sailor number 3!
    &marine;  #打印 Hello, sailor number 4!

    返回值

    Perl中,所有子程序都有一个返回值,但并非所有返回值都有用,这要看具体进行的是什么操作。

    子程序执行过程中最后一次运算的结果,不管它是什么,会被自动当作返回值。

    sub sum_of_fred_and_barney{
        print "I love u more than yesterday, but less than tomorrow.
    ";
        $fred + $barney;  #这就是返回值
    }
    
    $fred = 3;
    $barney = 4;
    $wilma = &sum_of_fred_and_barney;  #$wilma为7
    print "$wilma is $wilma.
    ";
    
    $betty = 3 * &sum_of_fred_and_barney;  #$betty为21
    print "$betty is $betty.
    ";

    注意:

    1.在子程序里添加额外的程序代码时,要注意检查最后执行的表达式是哪一个,确认它是你需要的返回值

    sub sum_of_fred_and_barney{
        print "I love u more than yesterday, but less than tomorrow.
    ";
        $fred + $barney;
        print "Hey, I'm returning a value now!
    ";  #糟糕!
    }

    最后执行的语句不是加法运算,而是print语句,它的返回值通常是1,表示“成功输出信息”。

     2.$fred + $barney相加的结果被丢弃了,启用警告信息时,会提示void context(空上下文),表示运算结果未被使用,既没有存储到变量里,也没有被任何函数使用。

     3.“最后执行的表达式”的准确含义就是最后执行的表达式,而非程序的最后一行代码。

    参数

    传递参数列表到子程序,在子程序调用的后面加上括在括号内的列表表达式即可。

    $n = &max(10,15);  #包含两个参数的子程序调用

    Perl会自动将参数列表化名为特殊的数组变量@_,该列表在子程序执行期间有效。

    第一个参数存储在$_[0],第二个参数存储在$_[1],依此类推。

    sub max{
        if($_[0] > $_[1]){
            $_[0];
        }else{
            $_[1];
        }
    }

    缺点:

    1.一堆下标,程序不雅观。

    2.不提示接收几个参数。

    @_变量是子程序的私有变量,加入已经有了全局变量@_,则该变量在子程序调用前会先被存起来,并在子程序返回时恢复原本的值。

    子程序中的私有变量

    可以使用my 操作符来创建私有变量,我们称之为词法变量

    my ($m, $n) = @_;

    变长参数列表

    把长度不限的列表作为参数传递给子程序,解决办法:

    1.检查@_数组的长度来判断参数个数是否符合预期

    sub max{
        if(@_!=2){
            ...
        }
    }

    2.让子程序自动适应任意数目的参数

    改进版的&max子程序:

    $max_num = &max(3,5,10,4,6);
    sub max{
        my $max_so_far = shift @_;
        foreach (@_){
            if($_ > $max_so_far){
                $max_so_far = $_;
            }
        }
        $max_so_far;
    }

    my声明的词法变量

    词法变量可以用在任何语句块内,并不仅限于子程序的语句块;

    1.ifwhileforeach内使用词法变量

    2.foreach的控制变量也可以声明为词法变量

    foreach my $rock(qw/bedrock slate lava/){
     ...
    }

    注意:

    1.词法变量的作用域受限于定义它的最内层语句块内,或文件内,只有语句块的代码才能使用这个词法变量。

    2.my操作符不会更改变量赋值时的上下文。

    my ($num) = @_;  #列表上下文
    my $num = @_;  #标量上下文

    3.my操作符不加括号时,只能用来声明靠近的单个词法变量。

    my $fred, $barney;  #错,没声明$barney
    my ($fred, $barney);  #两个都声明了

    4.最好对每个新变量都使用my声明,让它保持在自己所在的词法作用域内。

    5.词法变量无法存续,语句块一结束,它的值就会被抛弃。

    use strict编译指令

    use strict编译指令用于告诉Perl愿意接受更严格是限制,可以放在程序开头,或是任何需要强制使用约束规则的语句块或文件内。

    Perl 5.12开始,如果使用编译指令使用最低Perl版本号的话,就相当于隐式使用约束指令。

    use v5,12;  #自动加载use strict编译指令

    此限制只适用于创建新的变量,Perl的内置变量(比如$_@_)则完全不用事先声明。

    return操作符

    作用:立即停止运行并从子程序内返回某个值。

    my @names = qw/ fred barney betty dino wilma pebbles bamm-bamm /;
    my $result = &which_element_is("dino", @names);
    
    sub which_element_is{
        my($what,@array) = @_;
        foreach(0..$#array){  #数组中所有元素的索引
            if($what eq $array[$_]){
                return $_;  #一发现就提前返回
            }
        }
        -1;  #表示没找到符合条件的元素(可以省略return)
    }

    NOTE

    1.return最常见的用法:立即返回某个值,而不再执行子程序的其余部分。

    2.最后一行写成return -1也行,读起来更明朗,但因为是最后一行,可以省略return

    省略与号(&

    1.Perl通过语法规则判断它只能是子程序调用,可以省略与号。

    比如:将参数列表放进括号里,它就一定是子程序调用

    my @cards = shuffle(@deck_of_cards); 

    注意:

    假如这个子程序和Perl内置函数同名,为避免歧义,就必须使用与号调用。所以只能在没有同名内置函数的情况下省略与号。

    2.如果Perl的内部编译器已经见过子程序的定义,可以省略与号,并且参数列表两边的括号都可以不写。

    sub division{
        $_[0]] / $_[1];
    }
    my $quotient = division 355, 113;

    非标量返回值

    子程序不仅可以返回标量值,如果在列表上下文中调用它,还可以返回列表值。

    @c = &list_from_fred_to_barney;

    持久化私有变量

    在子程序中用my操作符可以创建私有变量,但每次调用子程序时,这个私有变量都会被重新定义。因为词法变量无法存续,语句块一结束,它的值就会被抛弃。用state操作符声明的变量可以在子程序的多次调用期间保留之前的值,而其作用域仍局限在子程序内部。

    state是从Perl 5.10开始引入的。

  • 相关阅读:
    LInq 与lambda表达式
    Java内存模型-jsr133规范介绍(转)
    Java多线程之Lock的使用(转)
    有一个很大的整数list,需要求这个list中所有整数的和,写一个可以充分利用多核CPU的代码,来计算结果(转)
    CountDownLatch
    CyclicBarrier
    java设计模式演示样例
    2012毕业找工作记录点滴
    Objective-C语法之代码块(block)的使用
    权限表设计之代码解析
  • 原文地址:https://www.cnblogs.com/yd-yfb/p/13943696.html
Copyright © 2020-2023  润新知