首页›文章›通过given-when打造perl的switch语句

通过given-when打造perl的switch语句

计算机技术 · perl 程序开发2012-01-150次浏览0 个评论

Perl中没有switch语句,但是并不意味着Perl中不能执行像switch一样的功能。为了实现这个功能,perl提供了一个关键词given。Perl中的given-when控制结构能够根据given的参数,执行某个条件对应的语句块。下面我们通过几个例子来了解一下given的使用。

perl
 given( $var ) {
     when( /fred/i ) { say 'Name has fred in it' }
     when( /^Fred/ ) { say 'Name starts with Fred' }
     when( 'Fred'  ) { say 'Name is Fred' }
     default         { say "I don't see a Fred" }
     }

--如果$_不能满足任何when条件,perl就会执行default语句块。
看到这里你也许会说,Perl中的if-elsif-else语句不是一样可以完成这个例子吗,为什么还要用given-when语句呢,它还有存在的必要吗?实际上他们两个语句最大的不同在于given-when可以在满足某个条件的基础上,继续测试其他的条件,但if-elsif-else一旦满足了某个条件,就只能执行对应的那个语句块。实际上前面的例子可以写成如下的方式:

perl
 given( $ARGV[0] ) {
     when( $_ ~~ /fred/i ) { say 'Name has fred in it'; break }
     when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; break }
     when( $_ ~~ 'Fred'  ) { say 'Name is Fred'; break }
     default               { say "I don't see a Fred"; break }
     }

--按照这种写法,因为第一条测试语句如果传来的参数匹配/fred/i,后面的所有语句就没有机会执行了,这时候就会直接跳出控制结构。如果在when语句块的末尾使用continue,Perl就会尝试执行后续的when语句了,这也是if-elsif-else语句块力不能及的地方。当另一个when的条件满足时,会执行对应语句块。在每个when语句块的末尾写上continue,就意味着所有的条件判断都会执行:

perl
use 5.010;
 given( $ARGV[0] ) {
     when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
     when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
     when( $_ ~~ 'Fred'  ) { say 'Name is Fred'; continue } # 注意!
     default               { say "I don't see a Fred" }
     }

--实际上这样写是有问题的,这里的default总是会运行

text
 $ perl5.10.0 switch.pl Alfred
 Name has fred in it
 I don't see a Fred

--default块相当于一个测试条件永远为真的when语句。如果在default之前的when语句使用了continue,Per就会继续执行default语句。因此可以说default就是一个特殊的when:

perl
use 5.010;
 given( $ARGV[0] ) {
     when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
     when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
     when( $_ ~~ 'Fred'  ) { say 'Name is Fred'; continue } # 注意!
     when( 1 == 1        ) { say "I don't see a Fred" } # 相当于default语句块
     }

要解决这个问题,只要拿掉最后一个when的continue就可以了,改写成如下形式:

perl
use 5.010;
 given( $ARGV[0] ) {
     when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
     when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
     when( $_ ~~ 'Fred'  ) { say 'Name is Fred'; break } # 现在就对了!
     when( 1 == 1        ) { say "I don't see a Fred" }  # 这里的when(1==1)可改写成default
     }

多个项目的when匹配
有些时候需要遍历很多元素,但given只能一次接受一个参数,当然可以将given语句放到foreach里面循环测试。比如要遍历@names,依次将各元素赋值到$name,然后再用given:

perl
use 5.010;
 foreach my $name ( @names ) {
     given( $name ) {
         ...
         }
     }

如果使用given-when语句,想必大家首先想到的就是上面的方法,实际上要遍历多个元素时就就不必使用given了,使用foreach的简写形式,让它给当前正在遍历的元素起个化名$_。此外若要用智能匹配,当前元素就只能是$_。

perl
use 5.010;
 foreach ( @names ) { # 不要使用命名变量!
     when( /fred/i ) { say 'Name has fred in it'; continue }
     when( /^Fred/ ) { say 'Name starts with Fred'; continue }
     when( 'Fred'  ) { say 'Name is Fred'; }
     default         { say "I don't see a Fred" }
     }

一般在遍历的时候,总希望可以看到当前的工作状态。可以在foreach语句块中写上其他的语句,比如say:

perl
use 5.010;
 foreach ( @names ) { # 不要使用命名变量!
     say "\nProcessing $_";
     when( /fred/i ) { say 'Name has fred in it'; continue }
     when( /^Fred/ ) { say 'Name starts with Fred'; continue }
     when( 'Fred'  ) { say 'Name is Fred'; }
     say "Moving on to default...";
     default         { say "I don't see a Fred" }
     }

评论

0

评论加载中…

发表评论

0/2000