Chinaunix首页 | 论坛 | 博客
  • 博客访问: 564407
  • 博文数量: 201
  • 博客积分: 7734
  • 博客等级: 少将
  • 技术积分: 1994
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-09 19:18
文章分类

全部博文(201)

文章存档

2011年(28)

2010年(173)

分类:

2010-08-19 17:37:51

第四章:子程序
子程序名由字母、数字和下划线组成,但是不能以数字开头。
有时候会以&(与号)开头。
用sub关键字来定义子程序名,子程序名(不包含“与号”)
 

sub marine {
  $n += 1;
  print "Hello, sailor number $n!\n";
}


Perl中任何情况下你都不需要对子程序进行事先声明。子程序定义是全局的。
假如你定义了两个重名的子程序,那么后面的那个子程序会覆盖掉前面的。

调用子程序:
在子程序名前面加上“与号”来调用它。

&marine;


sub marine {
while ( $n < 10){
  $n += 1;
  print "Hello, sailor number $n!\n";
}
}
print &marine;

返回值:
子程序被调用时一定是作为表达式,某个部分,即使该表达式的求值结果不会被用到。

所有的子程序都有一个返回值。子程序没有“有返回值”和“没有返回值”之分。但并不
是所有的Perl子程序都包含有用的返回值。
 

sub sum_of_fred_and_barney {
  print "Hey, you called the sum_of_fred_and_barney subroutine!\n";
  $fred + $barney;    
#这就是返回值

}

$fred = 3;
$barney = 4;
$wilma = &sum_of_fred_and_barney;    
#$wailma为7

print "\$wilma is $wilma.\n";
$betty = 3 * &sum_of_fred_and_barney    
#$betty为21

print "\$betty is $betty.\n";

sub larger_of_fred_or_barney {
  if ( $fred > $barney ) {
     $fred;
     } else {
        $barney;
             }
}

===================================================================
sub sum_of_fred_and_barney {
  print "Hey, you called the sum_of_fred_and_barney subroutine!\n";
  $fred +$barney;    
#这不是返回值!

  print    "Hey, I'm returning a value now!\n";    
#糟糕!这不是我要的结果

}
上面返回值通常是1,代表“输出成功”。

参数:
传递参数列表(argument list)到子程序里,只要在子程序调用的后面加上被括号圈引的列表表达式(list expression)就行了。
$n = &max(10, 15); #包含两个参数的子程序调用

参数列表将会传入子程序,让子程序随意使用。当然,得先将这个列表存在某处。Perl会自动将参数列表化名为特殊的数组变量@_,


 

sub max {
    
#请比较它和子程序&larger_of_fred_or_barney的差异

    if ( $_[0] > $_[1]) {
     $_[0];
    } else {
     $_[1];
    }
    }
    
你可以那么写,但是,这里的一堆下标让程序变得不雅观,而且难以阅读、编写、检查和调试。
$n = &max(10,15,27);    
#糟糕,因为这个子程序只接受两个参数,多余的参数会被忽略。参数不足会得到undef。

子程序中的私有变量:
默认情况下,Perl中所有的变量都是全局变量,也就是说。在程序里的任何地方都可以访问它们,但是你可以随时运用一个操作符来创建私有的记法变量(lexical variables)。这个操作符就是my:


 

sub max {
  my($m,$n);    
#该语句块中的新私有变量

  ($m, $n) = @_;    
#将参数赋值给变量

  if ($m > $n) { $m } else {$n}
#因为这里程序是写在一行的,所以不用";"。

  }
  这个变量也可以简化:
  my ( $m , $n ) = @_;    
#将保存在@_中的参数赋值给具体的变量。

  
  在真实的Perl代码中,常常把更长的(任意长度的)列表作为参数传给子程序。这延续了Perl的理念”去除不必要的限制“;
 当然,子程序可以很容易地能过检查@_数组的长度来确定参数的个数是否正确。比方说,我们可以将&max写成如下的形式,检查它的参数列表:
sub max {
  if (@_ != 2) {
    print "WARNING! &max should get exactly two arguments!\n";
  my($m,$n);    
#该语句块中的新私有变量

  ($m, $n) = @_;    
#将参数赋值给变量

  if ($m > $n) { $m } else {$n}
#因为这里程序是写在一行的,所以不用";"。

  }
  这个变量也可以简化:
  my ( $m , $n ) = @_;    
#将保存在@_中的参数赋值给具体的变量。

  }
  
更好的&max子程序:
$maximum = &max ( 3, 5, 10, 4, 6);

sub max {
  my ($max_so_far) = shift @_;    
#数组的第一个值,暂时把它当成最大值

  foreach (@_) {                
#遍历数组@_中的其他元素

    if ($_ > $max_so_far) {        
#当前元素比$max_so_far更大吗?

     $max_so_far = $_;
    }
  }
  $max_so_far
}


上面的程序代码使用了一般称为”高水线(high-water mark)“的算法:大水过后,在最后一波浪消退时,高水线会标出最高的水位。$max_so_far记录了高水线,也就是我们见过的最大数字。

第一行程序代码会对参数数组@_进行shift操作,并将得到的3(范例程序的第一个参数)存入$max_so_far变量,所以@_现在的内容为(5,10,4,6)因为3已被移走。现在最大的数字是3.也就是第一个参数。

然后foreach循环会遍历参数列表@_里其他的值。循环的控制变量默认为$_(别忘记了@_和$_没有任何关系。它们的名称相似纯属巧合。循环第一次执行时,$_是5,而if进行比较时看到$_比$max_so_far还大,所以$max_so_far会被设成5新的高水线。

阅读(575) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~