19 May 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.
本来写好了的,不小心按了什么快捷键就没了。damn it!

given 开关语句

given-when 是种开关语句(经常有人问 Perl 5 中有没有开关语句,没有开关语句但有个 Switch 模块)。它有点类似于其他语言的 switch-case, 但更强大。(匹配可以是正则表达,函数等)。
一个简单的例子:
given $i { # 这里的 $i 可以是表达式也可以是函数等
    when ($_ != 2) { print '$i isnot 2'; }
    when 1 { print '$i is 1'; }
    print 'b';
    when &foo($_) { print '&foo($i) return true'; }
    when m/^^a/ { print '$i is start with a'; }
    default { print 'default output'; }
}
几点说明:
  1. when VALUE 其实是 when $_ ~~ VALUE 的缩写
  2. default 必须放在所有 when 之后。因为 default 是在所有 when 不匹配后才执行。当然你也可以没有 default
    default 的作用等同于 when ture { ... }
  3. 如果匹配了一个 when, 那么 when 下面的语句将不会执行,匹配后直接跳出。所以这里的 when 1 不会被执行(被上一句执行后跳出了)。
  4. given 块的执行顺序与普通块一样,块里允许存在 when 之外的东西(比如这里的 print 'b';)。
    当 $i 不为 2 时输出 $i isnot 2 而不执行print 'b'; 当为 2 时,按顺序会执行 prin 'b';
  5. when 总是智能匹配 $_, 不管是不是在 given 中。(它可以在 for, while, CATCH 等中存在,只要有 $_ 就可以使用 when)。代码例子:
    for (qw(1 2 3)) {
        when 1 { say '1'; }
        when 3 { say '3'; }
        default { say 'not 1, not 3'; }
    }
    最后的结果为 1(换行)not 1, not 3(换行)3(换行)
    pring 与 say 的区别在于 say 会在后面输出 \n
  6. 我们可以使用 break 来跳出当前 when 和当前块。注意 break 只能在 when 里面而不是外面。例如:
    given $i {
        when 1 {
            print "1";
            break;
            print "11"; # 这句不会被输出,因为 break 跳出了整个循环
        }
        #break; # 出错,break 不能在 when 外面
        default { print "default output"; }
    }
    当 $i 为 1 时输出 1,而没有 11
  7. continue 用来跳出当前 when 而继续执行下一语句(没有跳出当前块)。例如:
    given $i {
        when 2 {
            print "2";
            continue;
            print '22'; # 这句不会被输出,因为 continue 跳出了这个 when 2
        }
        default { print "default output"; }
    }
    当 $i 为 2 时输出 2default output.
  8. 在 for 循环中, break 只跳出当前循环而进入下一循环(不是跳出整个 for 循环)。如果你要跳出整个循环,可以使用 last。我们可以用 next 来代替 break, 因为它表达意思更清晰。
    for (qw(1 2 3)) {
        when 1 {
            say '1';
            break; # next is better
            say '11'; # 这句不会输出
        }
        when 2 {
            say '2';
            last;
        }
        when 3 {
            say '3';
        }
        default { say 'default output'; }
    }
    当 $_ 为 1 时输出 1 (没有输出 11);当为 2 时输出 2 并且执行 last, 所以 when 3 不会被执行。
  9. 如果你使用的带名字的 for 循环,那么第一个带名字变量别名于 $_
    my @foo = (1,2,3);
    for @foo -> $foo { # 后面的 when 里的 $_ 就别名于 $foo
    for @foo -> $foo1, $foo2 { # 后面的 when 里的 $_ 别名于 $foo1
    

eval && try

在 Perl 5 中 eval 不仅能运行字符串也能运行块,而在 Perl 6 中 eval 只能运行字符串,块的话我们用 try 来运行。而错误变量将不再是 [email protected], 而统一变为 $!
my $a = 0;
eval('$a = 1 / $a');
print $! if $!; # Illegal division by zero

try {
    my $x = 1;
    my $x = 0; # $x 不能定义两次
    CATCH {
        say $!;
    }
}

Correct me if I'm wrong

See u next time.


blog comments powered by Disqus