Category: Perl6 Keywords: Perl6 given
本来写好了的,不小心按了什么快捷键就没了。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'; }
}
几点说明:
- when VALUE 其实是 when $_ ~~ VALUE 的缩写
- default 必须放在所有 when 之后。因为 default 是在所有 when 不匹配后才执行。当然你也可以没有 default
default 的作用等同于 when ture { ... } - 如果匹配了一个 when, 那么 when 下面的语句将不会执行,匹配后直接跳出。所以这里的 when 1 不会被执行(被上一句执行后跳出了)。
- given 块的执行顺序与普通块一样,块里允许存在 when 之外的东西(比如这里的 print 'b';)。
当 $i 不为 2 时输出 $i isnot 2 而不执行print 'b'; 当为 2 时,按顺序会执行 prin 'b'; - 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 - 我们可以使用 break 来跳出当前 when 和当前块。注意 break 只能在 when 里面而不是外面。例如:
当 $i 为 1 时输出 1,而没有 11given $i { when 1 { print "1"; break; print "11"; # 这句不会被输出,因为 break 跳出了整个循环 } #break; # 出错,break 不能在 when 外面 default { print "default output"; } } - continue 用来跳出当前 when 而继续执行下一语句(没有跳出当前块)。例如:
given $i { when 2 { print "2"; continue; print '22'; # 这句不会被输出,因为 continue 跳出了这个 when 2 } default { print "default output"; } }当 $i 为 2 时输出 2default output. - 在 for 循环中, break 只跳出当前循环而进入下一循环(不是跳出整个 for 循环)。如果你要跳出整个循环,可以使用 last。我们可以用 next 来代替 break, 因为它表达意思更清晰。
当 $_ 为 1 时输出 1 (没有输出 11);当为 2 时输出 2 并且执行 last, 所以 when 3 不会被执行。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'; } } - 如果你使用的带名字的 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 来运行。而错误变量将不再是 $@, 而统一变为 $!my $a = 0;
eval('$a = 1 / $a');
print $! if $!; # Illegal division by zero
try {
my $x = 1;
my $x = 0; # $x 不能定义两次
CATCH {
say $!;
}
}