Perl 子例程



  • 子例程

    Perl 子例程或函数是一起执行任务的一组语句。您可以将代码分成单独的子例程。如何在不同的子例程之间划分代码取决于您,但是从逻辑上来说,划分通常是使每个函数执行特定任务。Perl 交替使用术语子例程,方法和功能。
  • 定义并调用子程序

    Perl 编程语言中子例程定义的一般形式如下:
    
    sub subroutine_name {
       body of the subroutine
    }
    
    
    调用 Perl子例程的典型方式如下-
    
    subroutine_name( list of arguments );
    
    
    在Perl 5.0之前的版本中,调用子例程的语法略有不同,如下所示。这仍然可以在最新版本的Perl中使用,但不建议这样做,因为它会绕过子例程原型。
    
    &subroutine_name( list of arguments );
    
    
    让我们看下面的示例,该示例定义一个简单的函数,然后调用它。由于Perl在执行程序之前先对其进行编译,因此在哪里声明子例程都没有关系。
    
    # Function definition
    sub Hello {
       print "Hello, World!\n";
    }
    
    # Function call
    Hello();
    
    
    尝试一下
  • 将参数传递给子例程

    您可以像在任何其他编程语言中一样将各种参数传递给子例程,并且可以使用特殊数组@_在函数内部访问它们。因此,函数的第一个参数位于$_[0]中,第二个参数位于$_[1]中,依此类推。您可以像任何标量一样将数组和散列作为参数传递,但是传递多个数组或散列通常会导致它们失去各自的标识。因此,我们将使用引用(在下一章中进行说明)来传递任何数组或哈希。
    让我们尝试以下示例,该示例获取一个数字列表,然后输出其平均值-
    
    # Function definition
    sub Average {
       # get total number of arguments passed.
       $n = scalar(@_);
       $sum = 0;
    
       foreach $item (@_) {
          $sum += $item;
       }
       $average = $sum / $n;
    
       print "Average for the given numbers : $average\n";
    }
    
    # Function call
    Average(10, 20, 30);
    
    
    尝试一下
  • 将列表传递给子例程

    由于@_变量是一个数组,因此可用于将列表提供给子例程。但是,由于Perl接受和解析列表和数组的方式,可能很难从@_中提取单个元素。如果您必须将列表与其他标量参数一起传递,则将list作为最后一个参数,如下所示-
    
    # Function definition
    sub PrintList {
       my @list = @_;
       print "Given list is @list\n";
    }
    $a = 10;
    @b = (1, 2, 3, 4);
    
    # Function call with list parameter
    PrintList($a, @b);
    
    
    尝试一下
  • 将哈希传递给子例程

    当您向接受列表的子例程或运算符提供哈希值时,哈希值将自动转换为键/值对列表。例如-
    
    # Function definition
    sub PrintHash {
       my (%hash) = @_;
    
       foreach my $key ( keys %hash ) {
          my $value = $hash{$key};
          print "$key : $value\n";
       }
    }
    %hash = ('name' => 'Tom', 'age' => 19);
    
    # Function call with hash parameter
    PrintHash(%hash);
    
    
    尝试一下
  • 从子程序返回值

    您可以像使用其他任何编程语言一样从子例程返回值。如果您没有从子例程中返回值,那么子例程中最后执行的任何计算都会自动返回值。您可以像任何标量一样从子例程返回数组和散列,但是返回多个数组或散列通常会导致它们失去各自的标识。因此,我们将使用引用(在下一章中进行说明)从函数返回任何数组或哈希。
    让我们尝试以下示例,该示例获取数字列表,然后返回其平均值-
    
    # Function definition
    sub Average {
       # get total number of arguments passed.
       $n = scalar(@_);
       $sum = 0;
    
       foreach $item (@_) {
          $sum += $item;
       }
       $average = $sum / $n;
    
       return $average;
    }
    
    # Function call
    $num = Average(10, 20, 30);
    print "Average for the given numbers : $num\n";
    
    
    尝试一下
  • 子例程中的私有变量

    默认情况下,Perl中的所有变量都是全局变量,这意味着可以从程序中的任何位置访问它们。但是您可以随时使用my运算符创建称为词法变量的私有变量。在我的操作者地限制在其中它可以被用来访问和一个特定的代码区域的变量。在该区域之外,无法使用或访问此变量。该区域称为其范围。词法作用域通常是一组带有花括号的代码块,例如定义子例程主体的代码块或标记if,while,for,foreach和eval语句的代码块的代码块。
    以下示例显示了如何使用我的运算符定义单个或多个私有变量-
    
    sub somefunc {
       my $variable; # $variable is invisible outside somefunc()
       my ($another, @an_array, %a_hash); # declaring many variables at once
    }
    
    
    让我们检查以下示例,以区分全局变量和私有变量:
    
    # Global variable
    $string = "Hello, World!";
    
    # Function definition
    sub PrintHello {
       # Private variable for PrintHello function
       my $string;
       $string = "Hello, Perl!";
       print "Inside the function $string\n";
    }
    # Function call
    PrintHello();
    print "Outside the function $string\n";
    
    
    尝试一下
  • 通过local()的临时值

    在当地主要是用来当一个变量的当前值必须是调用的子程序可见。局部变量只是为全局变量(临时包)提供临时值。这称为动态作用域。词法作用域由my完成,其工作方式更像C的自动声明。如果将多个变量或表达式赋给local,则必须将它们放在括号中。该运算符的工作方式是将这些变量的当前值保存在其参数列表中的隐藏堆栈中,并在退出块,子例程或eval时恢复它们。
    让我们检查以下示例以区分全局变量和局部变量-
    
    # Global variable
    $string = "Hello, World!";
    
    sub PrintHello {
       # Private variable for PrintHello function
       local $string;
       $string = "Hello, Perl!";
       PrintMe();
       print "Inside the function PrintHello $string\n";
    }
    sub PrintMe {
       print "Inside the function PrintMe $string\n";
    }
    
    # Function call
    PrintHello();
    print "Outside the function $string\n";
    
    
    尝试一下
  • 通过 state() 的状态变量

    词汇变量还有另一种类型,类似于私有变量,但是它们保持其状态,并且不会在多次调用子例程时被重新初始化。这些变量是使用状态运算符定义的,并且从Perl 5.9.4开始可用。让我们检查以下示例以演示状态变量的使用-
    
    use feature 'state';
    
    sub PrintCount {
       state $count = 0; # initial value
    
       print "Value of counter is $count\n";
       $count++;
    }
    
    for (1..5) {
       PrintCount();
    }
    
    
    尝试一下
    在Perl 5.10之前,您必须像这样编写它-
    
    #!/usr/bin/perl
    
    {
       my $count = 0; # initial value
    
       sub PrintCount {
          print "Value of counter is $count\n";
          $count++;
       }
    }
    
    for (1..5) {
       PrintCount();
    }
    
    
  • 子例程调用上下文

    子例程或语句的上下文定义为期望的返回值的类型。这使您可以使用一个函数,该函数根据用户期望接收的内容返回不同的值。例如,以下localtime()在标量上下文中调用时返回一个字符串,但是在列表上下文中调用时返回一个列表。
    
    my $datestring = localtime( time );
    
    
    在此示例中,$timestr的值现在是由当前日期和时间组成的字符串,例如Thu Nov 30 15:21:332000。反之-
    
    ($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);
    
    
    现在,各个变量包含由localtime()子例程返回的相应值。